在Asp .net core 中通过属性映射实现动态排序和数据塑形
目录
- 属性映射服务实现
- 动态排序
- 数据塑形
属性映射服务实现

public class PropertyMappingValue
{
public IEnumerable DestinationProperties { get; private set; }
public PropertyMappingValue(IEnumerable destinationProperties)
{
DestinationProperties = destinationProperties;
}
}
public class PropertyMapping : IPropertyMapping
{
public Dictionary _mappingDictionary { get; set; }
public PropertyMapping(Dictionary mappingDictionary)
{
_mappingDictionary = mappingDictionary;
}
}
public class PropertyMappingService : IPropertyMappingService
{
//PropertyMapping
private Dictionary _touristRoutePropertyMapping =
new Dictionary(StringComparer.OrdinalIgnoreCase)
{
{"Id", new PropertyMappingValue(new List(){"Id"}) },
{"Title", new PropertyMappingValue(new List(){"Title"}) },
{"Rating", new PropertyMappingValue(new List(){"Rating"}) },
{"OriginalPrice", new PropertyMappingValue(new List(){"OriginalPrice"})},
};
//PropertyMappings
private IList _propertyMappings
= new List();
public PropertyMappingService()
{
_propertyMappings.Add(
new PropertyMapping (_touristRoutePropertyMapping)
);
}
//GetPropertyMapping
public Dictionary
GetPropertyMapping()
{
var matchingMapping =
_propertyMappings.OfType>();
if (matchingMapping.Count() == 1)
{
return matchingMapping.First()._mappingDictionary;
}
throw new Exception($"Cannot find exact property mapping instance for <{typeof(TSource)}, {typeof(TDestination)}>");
}
//IsMappingExists
public bool IsMappingExists(string fields)
{
var propertyMapping = GetPropertyMapping();
if (string.IsNullOrWhiteSpace(fields))
{
return true;
}
var fieldsAfterSplit = fields.Split(",");
foreach (var field in fieldsAfterSplit)
{
var trimmedField = field.Trim();
var indexOfFirstSpace = trimmedField.IndexOf(" ");
var propertyName = indexOfFirstSpace == -1 ?
trimmedField : trimmedField.Remove(indexOfFirstSpace);
if (!propertyMapping.ContainsKey(propertyName))
{
return false;
}
}
return true;
}
//IsPropertiesExists
public bool IsPropertiesExists(string fields)
{
if (string.IsNullOrWhiteSpace(fields))
{
return true;
}
var fieldsAfterSplit = fields.Split(',');
foreach (var field in fieldsAfterSplit)
{
var propertyName = field.Trim();
var propertyInfo = typeof(T)
.GetProperty(
propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance
);
if (propertyInfo == null)
{
return false;
}
}
return true;
}
}
注入服务
动态排序
在Helper中扩展IQueryable封装了ApplySort方法实现动态排序
public static class IQueryableExtensions
{
public static IQueryable ApplySort(
this IQueryable source,
string orderBy,
Dictionary mappingDictionary
)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (mappingDictionary == null)
{
throw new ArgumentNullException("mappingDictionary");
}
if (string.IsNullOrWhiteSpace(orderBy))
{
return source;
}
var orderByString = string.Empty;
var orderByAfterSplit = orderBy.Split(',');
foreach (var order in orderByAfterSplit)
{
var trimmedOrder = order.Trim();
var orderDescending = trimmedOrder.EndsWith(" desc");
var indexOfFirstSpace = trimmedOrder.IndexOf(" ");
var propertyName = indexOfFirstSpace == -1
? trimmedOrder
: trimmedOrder.Remove(indexOfFirstSpace);
if (!mappingDictionary.ContainsKey(propertyName))
{
throw new ArgumentException($"Key mapping for {propertyName} is missing");
}
var propertyMappingValue = mappingDictionary[propertyName];
if (propertyMappingValue == null)
{
throw new ArgumentNullException("propertyMappingValue");
}
foreach (var destinationProperty in
propertyMappingValue.DestinationProperties)
{
orderByString = orderByString +
(string.IsNullOrWhiteSpace(orderByString) ? string.Empty : ", ")
+ destinationProperty
+ (orderDescending ? " descending" : " ascending");
}
}
return source.OrderBy(orderByString);
}
}
在repository中使用
数据塑形
安装Nuget包
在Helper中封装了IEnumerableExtensions、ObjectExtensions,实现对数据的动态塑形。
public static class IEnumerableExtensions
{
public static IEnumerable ShapeData(
this IEnumerable source,
string fields
)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
var expandoObjectList = new List();
//避免在列表中遍历数据,创建一个属性信息列表
var propertyInfoList = new List();
if (string.IsNullOrWhiteSpace(fields))
{
// 希望返回动态类型对象ExpandoObject所有的属性
var propertyInfos = typeof(TSource)
.GetProperties(BindingFlags.IgnoreCase
| BindingFlags.Public | BindingFlags.Instance);
propertyInfoList.AddRange(propertyInfos);
}
else
{
//逗号来分隔字段字符串
var fieldsAfterSplit = fields.Split(',');
foreach (var filed in fieldsAfterSplit)
{
// 去掉首尾多余的空格,获得属性名称
var propertyName = filed.Trim();
var propertyInfo = typeof(TSource)
.GetProperty(propertyName, BindingFlags.IgnoreCase
| BindingFlags.Public | BindingFlags.Instance);
if (propertyInfo == null)
{
throw new Exception($"属性 {propertyName} 找不到" +
$" {typeof(TSource)}");
}
propertyInfoList.Add(propertyInfo);
}
}
foreach (TSource sourceObject in source)
{
// 创建动态类型对象, 创建数据塑性对象
var dataShapedObject = new ExpandoObject
foreach (var propertyInfo in propertyInfoList)
{
//获得对应属性的真实数据
var propertyValue = propertyInfo.GetValue(sourceObjec
((IDictionary)dataShapedObject)
.Add(propertyInfo.Name, propertyValue);
expandoObjectList.Add(dataShapedObject);
}
return expandoObjectList;
}
}
public static class ObjectExtensions
{
public static ExpandoObject ShapeData(
this TSource source,
string fields
)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
var dataShapedObject = new ExpandoObject();
if (string.IsNullOrWhiteSpace(fields))
{
var propertyInfos = typeof(TSource)
.GetProperties(BindingFlags.IgnoreCase |
BindingFlags.Public | BindingFlags.Instance);
foreach (var propertyInfo in propertyInfos)
{
var propertyValue = propertyInfo.GetValue(source);
((IDictionary)dataShapedObject)
.Add(propertyInfo.Name, propertyValue);
}
return dataShapedObject;
}
var fieldsAfterSplit = fields.Split(',');
foreach (var field in fieldsAfterSplit)
{
var propertyName = field.Trim();
var propertyInfo = typeof(TSource)
.GetProperty(propertyName,
BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (propertyInfo == null)
{
throw new Exception($"Property {propertyName} wasn't found " +
$"on {typeof(TSource)}");
}
var propertyValue = propertyInfo.GetValue(source);
((IDictionary)dataShapedObject)
.Add(propertyInfo.Name, propertyValue);
}
return dataShapedObject;
}
}
在控制器的Action中使用

