Retrieving an Expression from a property and adding it to an expression tree

别等时光非礼了梦想. 提交于 2019-12-05 13:24:55

When you call Expression.Invoke, the first argument must be an existing LambdaExpression - it can't be an Expression to a LambdaExpression. Or in other words: it isn't going to evaluate Product.Blarg per row and use a different sub-expression each time.

Instead, you would retrieve this lambda first, perhaps making it static and accessing it via reflection if you only know it by name:

var lambda = (LambdaExpression) typeof(Product)
          .GetProperty("Blarg").GetValue(null,null);

And pass lambda in as the argument to Expression.Invoke; here's a fully working LINQ-to-Objects example showing this (via AsQueryable()):

using System;
using System.Linq;
using System.Linq.Expressions;
public partial class Product
{
    public static Expression<Func<Product, string>> Blarg
    {
        get { return product => product.ProductModelID.HasValue ? "Blarg?" : "Blarg!"; }
    }
    public int? ProductModelID { get; set; }

    static void Main()
    {
        var lambda = (LambdaExpression)typeof(Product)
          .GetProperty("Blarg").GetValue(null, null);

        var productParameter = Expression.Parameter(typeof(Product), "product");

        // The Problem
        var groupExpression = Expression.Lambda<Func<Product, string>>(
            Expression.Invoke(
                lambda,
                productParameter),
            productParameter);

        var data = new[] {
            new Product { ProductModelID = 123},
            new Product { ProductModelID = null},
            new Product { ProductModelID = 456},
        };
        var qry = data.AsQueryable().GroupBy(groupExpression).ToList();
    }
}
var qry = data.AsQueryable().GroupBy(Blarg).ToList();

That works, same as Marc's code.

Note: Blarg is already correct, there is no reason to 're-invoke' it.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!