屬性對映服務實現

public class PropertyMappingValue
{
public IEnumerable<string> DestinationProperties { get; private set; }
public PropertyMappingValue(IEnumerable<string> destinationProperties)
{
DestinationProperties = destinationProperties;
}
}
public class PropertyMapping<TSource, TDestination> : IPropertyMapping
{
public Dictionary<string, PropertyMappingValue> _mappingDictionary { get; set; }
public PropertyMapping(Dictionary<string, PropertyMappingValue> mappingDictionary)
{
_mappingDictionary = mappingDictionary;
}
}
public class PropertyMappingService : IPropertyMappingService
{
//PropertyMapping
private Dictionary<string, PropertyMappingValue> _touristRoutePropertyMapping =
new Dictionary<string, PropertyMappingValue>(StringComparer.OrdinalIgnoreCase)
{
{"Id", new PropertyMappingValue(new List<string>(){"Id"}) },
{"Title", new PropertyMappingValue(new List<string>(){"Title"}) },
{"Rating", new PropertyMappingValue(new List<string>(){"Rating"}) },
{"OriginalPrice", new PropertyMappingValue(new List<string>(){"OriginalPrice"})},
}; //PropertyMappings
private IList<IPropertyMapping> _propertyMappings
= new List<IPropertyMapping>(); public PropertyMappingService()
{
_propertyMappings.Add(
new PropertyMapping<TouristRouteDto, TouristRoute> (_touristRoutePropertyMapping)
);
} //GetPropertyMapping
public Dictionary<string, PropertyMappingValue>
GetPropertyMapping<TSource, TDestination>()
{
var matchingMapping =
_propertyMappings.OfType<PropertyMapping<TSource, TDestination>>(); 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<TSource, TDestination>(string fields)
{
var propertyMapping = GetPropertyMapping<TSource, TDestination>(); 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<T>(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<T> ApplySort<T>(
this IQueryable<T> source,
string orderBy,
Dictionary<string, PropertyMappingValue> 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<ExpandoObject> ShapeData<TSource>(
this IEnumerable<TSource> source,
string fields
)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
} var expandoObjectList = new List<ExpandoObject>(); //避免在列表中遍歷資料,建立一個屬性資訊列表
var propertyInfoList = new List<PropertyInfo>(); 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<string, object>)dataShapedObject)
.Add(propertyInfo.Name, propertyValue); expandoObjectList.Add(dataShapedObject);
} return expandoObjectList;
}
}
public static class ObjectExtensions
{
public static ExpandoObject ShapeData<TSource>(
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<string, object>)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<string, object>)dataShapedObject)
.Add(propertyInfo.Name, propertyValue);
} return dataShapedObject;
}
}

在控制器的Action中使用