我有一个关于IQueryable的扩展方法的初稿,它有一个GroupBy的覆盖,它应该由一个命名属性分组。
在你提问之前,我没有使用Dynamic Expression API,即动态Linq,因为我无法弄清楚如何使用它来访问每个组的计数。该库中的GroupBy方法返回非泛型IQueryable
,而不是我需要的IQueryable<IGrouping<>>
。如果有办法通过该库获取计数,我将很乐意接受一个答案,告诉我如何。也许某种语法我找不到string elementSelector
参数中的文档?
代码:
public static IQueryable<IGrouping<object, T>> GroupBy<T>(this IQueryable<T> source, string propertyName)
{
ParameterExpression param = Expression.Parameter(typeof(T), String.Empty);
MemberExpression property = Expression.PropertyOrField(param, propertyName);
LambdaExpression group = Expression.Lambda(property, param);
MethodCallExpression call = Expression.Call(
typeof(Queryable),
"GroupBy",
new[] { typeof(T), property.Type },
source.Expression,
Expression.Quote(group));
return source.Provider.CreateQuery<IGrouping<object, T>>(call);
}
我这样消耗它:
public IEnumerable<Category> GetCategories(IQueryable<T> entities, string property)
{
var haba = entities.GroupBy(property);
var categories = haba.Select(group => new Category(group.Key.ToString(), group.Count()));
return categories.ToArray();
}
只要我的属性是string类型,它就可以正常工作。但是,如果我尝试在int或bool属性上使用它,我会在调用CreateQuery时遇到以下错误:
参数表达式有类型 System.Linq.IQueryable
1[System.Linq.IGrouping
2 [System.Int32,DerivedEntity1]] 当类型 System.Collections.Generic.IEnumerable1[System.Linq.IGrouping
2 [System.Object的,DerivedEntity1]] 预计。参数名称:表达式
我注意到它期待IEnumerable
泛型而不是IQueryable
,这很奇怪。但是一个非常好的提示。如果不执行IEnumerable
,则无法将IQueryable
投射到AsQueryable()
。那么问题是,为什么它会给我一个IEnumerable
而不是IQueryable
?当我传入一个字符串属性的propertyName时,为什么它不会以同样的方式失败?
我应该提一下,我的IQueryable
是NhQueryable
的实例,来自NHibernate,就是这样。
答案 0 :(得分:2)
我认为您的代码中缺少来自值类型的装箱:
public static IQueryable<IGrouping<object, T>> GroupBy<T>(this IQueryable<T> source, string propertyName)
{
ParameterExpression param = Expression.Parameter(typeof(T), String.Empty);
MemberExpression property = Expression.PropertyOrField(param, propertyName);
UnaryExpression convert = Expression.Convert(property, typeof(object));
LambdaExpression group = Expression.Lambda(convert, param);
MethodCallExpression call = Expression.Call(
typeof(Queryable),
"GroupBy",
new[] { typeof(T), typeof(object) },
source.Expression,
Expression.Quote(group));
return source.Provider.CreateQuery<IGrouping<object, T>>(call);
}
答案 1 :(得分:0)
您是否尝试过更改方法定义以包含其他类似的通用类型
public static IQueryable<IGrouping<O, T>> GroupBy<O, T>(this IQueryable<T> source, string propertyName)
{
return source.Provider.CreateQuery<IGrouping<O, T>>(call);
}
消费它像:
var haba = entities.GroupBy<int, Category>(property);