c# - 使用字段名称作为字符串调用 OrderBy()

标签 c# linq entity-framework

<分区>

我正在使用 .NET 4.51、EF 6

我多次调用我的存储库层,我需要在其中按升序或降序对单个字段进行一些基本排序,例如:

enter image description here

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 中使用

如果需要,您将需要实现重载。

关于c# - 使用字段名称作为字符串调用 OrderBy(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32061770/

相关文章:

c# - 如果结果为空,IEnumerable.FirstOrDefaultAsync( predicate )?.ContinueWith() 是否返回?

Linq 因 Range 变量 'Username' 隐藏变量而出错

c# - Linq使用案例

entity-framework - 模拟 Entity Framework 模型?

c# - 这两种继承有什么区别?

c# - 如何创建通用数组来添加任何 View

c# - SQL查询单独日期

c# - 尝试使用 LINQ 读取 xml 文件

entity-framework - Entity Framework 双向关系未加载包括

c# - 如何发送表情符号?