c# - 为动态对象创建 linq 表达式树

标签 c# linq dynamic lambda expression-trees

我正在尝试动态构建表达式树以进行排序。排序将在我的 Web api 的操作过滤器中进行。因此对象的类型在运行时之前都是未知的。

概述如下:
在操作过滤器级别:

IEnumerable<object> model = null;
context.Response.TryGetContentValue(out model);
model=model.OrderByExtension(orderByField, orderDirection);
context.Response.Content=new ObjectContent<IEnumerable<object>>(model, new JsonMediaTypeFormatter());

扩展方法:

 public static IQueryable<T> OrderByExtension<T>(this IQueryable<T> source, string sortProperty, Sorting.SortingOption sortOrder)
        {
            var type = source.FirstOrDefault().GetType(); //Gets the type of object passed, since typeof(T) is only object at this point
            var property = type.GetProperty(sortProperty);
            var parameter = Expression.Parameter(type, "p");
            var propertyAccess = Expression.MakeMemberAccess(parameter, property);
            var orderByExp = Expression.Lambda(propertyAccess, parameter);
            var typeArguments = new Type[] { typeof(T), property.PropertyType };
            var methodName = sortOrder == Sorting.SortingOption.Asc ? "OrderBy" : "OrderByDescending";
            var resultExp = Expression.Call(typeof(Queryable), methodName, typeArguments, source.Expression, Expression.Quote(orderByExp));

            return source.Provider.CreateQuery<T>(resultExp);
        }

在 Expression.Call - 我收到错误:“System.Linq.Queryable”类型上的泛型方法“OrderByDescending”与提供的类型参数和参数不兼容。

我假设调用 OrderBy 方法时,“对象”类型与实际类型不匹配。

有什么办法可以让它发挥作用吗?

提前致谢。 ps:我还尝试通过 .MakeGenericMethod 创建 OrderBy 的通用方法 - 但没有成功。

最佳答案

问题在于您生成的是实际基础类型的函数表达式,而不是源表达式的类型 (object)。您需要在生成的表达式中添加对您的类型的转换。

public static IQueryable<object> OrderByExtension(this IQueryable<object> source, string sortProperty, SortOrder sortOrder = SortOrder.Unspecified)
{
    var sourceType = typeof(object);
    var underlyingType = source.First().GetType();
    var propertyType = underlyingType.GetProperty(sortProperty).PropertyType;
    var param = Expression.Parameter(sourceType);
    var body = Expression.Property(
        Expression.Convert(param, underlyingType), sortProperty
    );
    var lambda = Expression.Lambda(body, param);

    var sortMethod = sortOrder == SortOrder.Descending ? "OrderByDescending" : "OrderBy";
    var expr = Expression.Call(typeof(Queryable), sortMethod, new Type[] { sourceType, propertyType },
        source.Expression, lambda
    );
    return source.Provider.CreateQuery<object>(expr);
}

关于c# - 为动态对象创建 linq 表达式树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37490834/

相关文章:

c# - MVVM 按钮内容属性不起作用

c# - 使用 LINQ 高效配对时间相关记录

angularjs - Angular Grid ag-grid columnDefs 动态改变

c++ - Cpp中的动态功能

c# - 类属性在程序集或命名空间外部只读

C# 本地 SQL 行返回 if 语句

c# - 检查 list1 内容是否与 list2 内容匹配

c# - LINQ:如何清空投影中的属性?

c# - 在字符串末尾找到匹配项时,使用 .Contains() 和 .ToLowerInvariant() 的 EF 查询结果没有匹配项

javascript - 基于先前选择的动态选择框