首页 > 解决方案 > C# LINQ OrderBy() 表达式,创建嵌套泛型类型

问题描述

我有一个class Person

class Person
{
   string Name;
   int Age;
   DateTime BirthDate;
}

我正在尝试通过给定的属性名称创建一个Expression来订购一个。IQueryable<Person>

public IQueryable<Person> Order(IQueryable<Person> input, string sortColumnName)
{
    Type type = typeof(Person);

    PropertyInfo propertyInfo = type.GetProperty(sortColumnName);
    Type pType = prop.Type;

    ParameterExpression param = Expression.Parameter(type, "y");
    Expression prop = param;

    prop = Expression.Property(prop, propertyInfo);

    // I want to achieve..
    // var orderExpression = Expression.Lambda<Func<Person, "pType">>(prop, param);

    // In order to do something like the above statement, 
    // I have to create a nested generic type of `Func<Person, "pType">`
              
    Type e1 = typeof(Expression<>);

    Type[] typeArgs = {typeof( Func <Person, pType>)};
     
    Type orderType = e1.MakeGenericType(typeArgs);

    // Need some help of how to create and use this Generic ""orderType"".

    // ....
    // Ultimately, it will by used somewhat like ...
    // 
    // var orderExpression = Expression.Lambda<"orderType">(prop, param);

    return input.OrderBy(orderExpression);
}

我对这种不一致的行为感到非常困惑Expression trees

在我的项目中,我有一个""IQueryable<Person>"".Where(w1)可以轻松接收Expression w1.

我只是想通过创建一个""IQueryable<Person>"".OrderBy(o1),
来成功使用一个Expression o1.

我宁愿将所有内容都保留为IQueryable<>,而不必来回转换为IEnumerable<>.

任何帮助,将不胜感激!

标签: c#entity-frameworklinqlinq-to-entitiesexpression-trees

解决方案


我会留下常见的解决方案。表达式树从一开始就是一场噩梦。

public IQueryable<T> Order(this IQueryable<T> input, string sortColumnName)
{
    Type type = typeof(T);

    var propertyInfo = type.GetProperty(sortColumnName);
    if (propertyInfo == null)
       throw new InvalidOperationException();

    var param = Expression.Parameter(type, "y");
    var orderLambda = Expression.Lambda(
       Expression.MakeMemberAccess(param, propertyInfo), 
       param);

    var queryExpr = Expression.Call(
        typeof(Queryable), 
        "OrderBy", 
         new Type[] { 
                input.ElementType, 
                propertyInfo.PropertyType },
        input.Expression,
        orderLambda);
    
    return input.Provider.CreateQuery<T>(queryExpr);
}

请注意,我可能会犯小错误,因为只是从内存中写入。


推荐阅读