c# - IQueryable GroupBy Lambda 表达式对于具有对象键的原始类型失败

标签 c# linq expression-trees iqueryable

我正在为 IQueryable<TSource> 创建 Lambda 表达式,以下是我的扩展方法代码,我需要像这样调用它:

queryableData.GroupBy<int,Product>("ID")

queryableData.GroupBy<string,Product>("Name")

public static IQueryable<IGrouping<TKey,TSource>> GroupBy<TKey,TSource>(this IQueryable<TSource> queryable, string propertyName)
    {
        // Access the propertyInfo, using Queryable Element Type (Make it Case insensitive)
        var propInfo = queryable.ElementType.GetProperty(propertyName,BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

        // Access the Collection / Queryable Type
        var collectionType = queryable.ElementType;

        // Creating Group Parameter Expression
        var groupParameterExpression = Expression.Parameter(collectionType, "g");

        // Create MemberEXpression with the Property (access the property of a Type)
        var propertyAccess = Expression.MakeMemberAccess(groupParameterExpression, propInfo);

        // Create Lambda Expression
        var lambdaExpression = Expression.Lambda<Func<TSource,TKey>>(propertyAccess, groupParameterExpression);

        // Return GroupBy result
        return queryable.GroupBy(lambdaExpression);
    }

我的目标是生成 Expression<Func<TSource,object>>而不是 Expression<Func<TSource,TKey>> ,这样就可以在不提供Key类型的情况下调用,代码如下:

public static IQueryable<IGrouping<object, TSource>> GroupByObjectKey<TSource>(this IQueryable<TSource> queryable, string propertyName)
    {
        // Access the propertyInfo, using Queryable Element Type (Make it Case insensitive)
        var propInfo = queryable.ElementType.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

        // Access the Collection / Queryable Type
        var collectionType = queryable.ElementType;

        // Creating Group Parameter Expression
        var groupParameterExpression = Expression.Parameter(collectionType, "g");

        // Create MemberEXpression with the Property (access the property of a Type)
        var propertyAccess = Expression.MakeMemberAccess(groupParameterExpression, propInfo);

        // Create Lambda Expression
        var lambdaExpression = Expression.Lambda<Func<TSource, object>>(propertyAccess, groupParameterExpression);

        // Return GroupBy result
        return queryable.GroupBy(lambdaExpression);
    }

现在我可以使它适用于字符串类型,如下所示:

queryableData.GroupBy<Product>("Name")

但它在下面调用整数类型时失败,异常如下所述:

queryableData.GroupBy<Product>("Id")

Expression of type 'System.Int32' cannot be used for return type 'System.Object'

这是一个明显的类型转换案例,但我很惊讶为什么一个类型会拒绝转换为 Object 基类,可能是什么原因,任何指针/建议

最佳答案

正如评论已经指出的那样,您需要向object 添加一个转换:

var convertToObject = Expression.Convert(propertyAccess, typeof(object));

var lambdaExpression = Expression.Lambda<Func<TSource, object>>(convertToObject, groupParameterExpression);

关于c# - IQueryable GroupBy Lambda 表达式对于具有对象键的原始类型失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46489176/

相关文章:

c# - 如何使用交易范围?

c# - 无法将元组添加到 BlockingCollection : Error CS1503 in C#

c# - 无法在 Entity Framework 中获取导航属性

c# - 表达式树是 C# 的核心语言功能吗?

c# - 使用 ExpressionVisitor 修改表达式以进行自动翻译

c# - 如何将编译器检查的属性名称/表达式树传递给自定义属性

javascript - Angular 5/6 : Handle File Download (w/Friendly File Name) from ASP. NET 核心 API HTTP

c# - 在我的项目中查找所有未使用的代码 (Rider/VSCode)

c# - 如何将文件中的项目读入项目列表并将属性设置为文件中的值?

c# - 如何在 LINQ 查询期间将 XML 属性(字符串)解析为(int)