我有一个IQueryable上的扩展方法的初稿,其中包含GroupBy的重写,该重写应按命名属性分组。
在你提问之前,我没有使用动态表达式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();
}
只要我的属性是字符串类型,它就可以正常工作。然而,如果我试图在int或bool属性上使用它,我会在调用CreateQuery时遇到以下错误:
参数表达式具有类型System.Linq.IQUERABLE
1[System.Linq.IGrouping
2[System.Int32,DerivedEntity1]当类型System.Collections.Generic.IEnumerable1[System.Linq.IGrouping
2[System.Object,DerivedEntity1]]预期。参数名称:表达式
我注意到它期望的是IEnumerable
泛型,而不是IQueryable
,这很奇怪。但这是个不错的建议。如果不执行AsQueryable()
,就无法将IEnumerable
强制转换为IQueryable
。那么问题是,为什么它给我一个IEnumerable
而不是IQueryable
?为什么当我为字符串属性传递propertyName时,它不会以同样的方式失败?
我应该提到我的IQueryable
是来自NHibernate的NhQueryable
的实例,也就是
我认为您的代码中缺少值类型的装箱:
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);
}
您是否尝试更改方法定义以包含另一个泛型类型,如so
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);