IQueryable GroupBy Lambda 表达式对于具有对象键的原始类型失败
IQueryable GroupBy Lambda expression fails for primitive types with object key
我正在为 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 base class,可能是什么原因,任何指针/建议
正如评论已经指出的那样,您需要将转换添加到 object
:
var convertToObject = Expression.Convert(propertyAccess, typeof(object));
var lambdaExpression = Expression.Lambda<Func<TSource, object>>(convertToObject, groupParameterExpression);
我正在为 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 base class,可能是什么原因,任何指针/建议
正如评论已经指出的那样,您需要将转换添加到 object
:
var convertToObject = Expression.Convert(propertyAccess, typeof(object));
var lambdaExpression = Expression.Lambda<Func<TSource, object>>(convertToObject, groupParameterExpression);