以下代码通过提供属性名称帮助我在运行时创建一个带有一个属性的GroupBy
,但是我无法创建一个复合GroupBy
,可以在多个属性上完成一个类型,任何建议/指针:
// Linqpad代码
void Main()
{
ParameterExpression parameterType = Expression.Parameter(typeof(string), "o");
IQueryable queryableRecords = Product.FetchQueryableProducts();
Expression expression = queryableRecords.GroupBy("Name");
var func = Expression.Lambda<Func<IQueryable<IGrouping<string, Product>>>>(expression)
.Compile();
func().Dump();
}
public static class ExpressionTreesExtension
{
public static Expression GroupBy(this IQueryable queryable, string propertyName)
{
var propInfo = queryable.ElementType.GetProperty(propertyName);
var collectionType = queryable.ElementType;
var groupParameterExpression = Expression.Parameter(collectionType, "g");
var propertyAccess = Expression.MakeMemberAccess(groupParameterExpression, propInfo);
var groupLambda = Expression.Lambda(propertyAccess, groupParameterExpression);
return Expression.Call(typeof(Queryable),
"GroupBy",
new Type[] { collectionType, propInfo.PropertyType },
queryable.Expression,
Expression.Quote(groupLambda));
}
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public static IQueryable<Product> FetchQueryableProducts()
{
List<Product> productList = new List<Product>()
{
new Product {Id=1, Name = "A"},
new Product {Id=1, Name = "B"},
new Product {Id=1, Name = "A"},
new Product {Id=2, Name = "C"},
new Product {Id=2, Name = "B"},
new Product {Id=2, Name = "C"},
};
return productList.AsQueryable();
}
}