我正在使用 .NET 4.51、EF 6
我多次调用我的存储库层,我需要在其中按升序或降序对单个字段进行一些基本排序,例如:
GetAllList()
的结果是 List<T>
.现在不幸的是 Id
我必须排序的字段并不总是称为 Id
Text
也不是 field 。它们可以是其他东西,例如 MyId
, SomeTextField
等等。
所以我想知道是否有办法可以执行 OrderBy()
和 OrderByDescending()
通过为字段名称提供字符串来创建子句,例如:
_Repository.GetAllList().OrderBy(r => r."SomeTextField")
通过这种方式,我可以将所有这些代码移动到一个通用方法中。
非常感谢任何指点。
这会起作用:
public static class LinqExtensions
{
private static PropertyInfo GetPropertyInfo(Type objType, string name)
{
var properties = objType.GetProperties();
var matchedProperty = properties.FirstOrDefault (p => p.Name == name);
if (matchedProperty == null)
throw new ArgumentException("name");
return matchedProperty;
}
private static LambdaExpression GetOrderExpression(Type objType, PropertyInfo pi)
{
var paramExpr = Expression.Parameter(objType);
var propAccess = Expression.PropertyOrField(paramExpr, pi.Name);
var expr = Expression.Lambda(propAccess, paramExpr);
return expr;
}
public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> query, string name)
{
var propInfo = GetPropertyInfo(typeof(T), name);
var expr = GetOrderExpression(typeof(T), propInfo);
var method = typeof(Enumerable).GetMethods().FirstOrDefault(m => m.Name == "OrderBy" && m.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
return (IEnumerable<T>) genericMethod.Invoke(null, new object[] { query, expr.Compile() });
}
public static IQueryable<T> OrderBy<T>(this IQueryable<T> query, string name)
{
var propInfo = GetPropertyInfo(typeof(T), name);
var expr = GetOrderExpression(typeof(T), propInfo);
var method = typeof(Queryable).GetMethods().FirstOrDefault(m => m.Name == "OrderBy" && m.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
return (IQueryable<T>) genericMethod.Invoke(null, new object[] { query, expr });
}
}
测试:
var r = new List<temp> {
new temp { a = 5 },
new temp { a = 1 },
new temp { a = 15 }
}.OrderBy("a");
给出正确的结果 (1, 5, 15) - 并将提供惰性执行以供您在 EF 中使用
如果需要,您将需要实现重载。