编写基本的表达式生成器

Writing a basic Expression Builder

我正在使用 Linq-to-Entities,一个查询需要动态加载 属性。查询如下所示:

var found = Context.IntegrateViews.GroupBy(x => x.TypeOfBed)
                   .Select(type => new TypeCounts
                            { Name = type.Key, Count = type.Count() }).ToList();

Group By 子句 运行 所在的 属性 是 TypeOfBed。现在我想 运行 这个关于不同属性的查询,例如,下次我想 运行 它时,假设 x.TypeOfChair 等等。为此,我需要在其中动态添加此 属性。

我正在尝试编写一个像这样的表达式生成器。

public Expression<Func<LookupFilterItem>> PropertyLambda(string propertyName)
{
    var param = Expression.Parameter(typeof(LookupFilterItem), "lookupItem");
    //type of x in above example is LookupFilterItem
    var propertyExpression = Expression.Property(param, propertyName);

    var returnExpr = Expression.Lambda<Func<LookupFilterItem>>(propertyExpression);
    return returnExpr;
    //If I Pass string "TypeOfBed" to this method, I am expecting it to return something like
    // lookupItem => lookupItem.TypeOfBed
}

我打算这样使用它:

var found = Context.IntegrateViews.GroupBy(PropertyLambda("TypeOfBed"))
                   .Select(type => new TypeCounts
                            { Name = type.Key, Count = type.Count() }).ToList();

但这不起作用,我收到一个编译时错误:

error CS0411: The type arguments for method 'System.Linq.Queryable.GroupBy(System.Linq.IQueryable, System.Linq.Expressions.Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

我做错了什么?

这似乎是语法问题。试试这个:

public Expression<Func<LookupFilterItem, string>> PropertyLambda(string propertyName)
    {
        var param = Expression.Parameter(typeof(LookupFilterItem), "lookupItem");
        var propertyExpression = Expression.Property(param, propertyName);
        var returnExpr = Expression.Lambda<Func<LookupFilterItem, string>>(propertyExpression, param);
        return returnExpr;
    }

以及用法:

var found = Context.IntegrateViews.GroupBy(PropertyLambda("TypeOfBed").Compile())
               .Select(type => new TypeCounts
                        { Name = type.Key, Count = type.Count() }).ToList();

另一种选择是使用 LINQ Dynamic Query Library :

using System.Linq.Dynamic;

var found = Context.IntegrateViews.AsQueryable().GroupBy("new(TypeOfBed)", "it")
                   .Select(new (Key.TypeOfBed as Name, Count() as Count)).ToList();