检索防爆pression从属性并将其添加到一个前pression树 [英] Retrieving an Expression from a property and adding it to an expression tree

查看:156
本文介绍了检索防爆pression从属性并将其添加到一个前pression树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图简化这个例子中,由于实际code,我玩的是更为复杂的。因此,尽管这个例子可能看起来很傻,多多包涵。比方说,我正在使用AdventureWorks数据库,我决定我要添加一个名为属性 Blarg 产品表返回包含code,我想在几个地方使用EX pression:

I've tried to simplify this example, as the actual code I'm playing with is more complex. So while this example may seem silly, bear with me. Let's say I'm working with the AdventureWorks database and I decide I want to add a property called Blarg to the Product table that returns an expression that contains code I would like to use in several places:

public partial class Product
{
    public Expression<Func<Product, string>> Blarg
    {
        get { return product => product.ProductModelID.HasValue ? "Blarg?" : "Blarg!"; }
    }
}

我想要做的就是创建一个前pression EX pression树,让它得到Product.Blarg防爆pression和GROUP BY的结果。事情是这样的:

What I want to do is create an expression expression tree, have it get the Expression from Product.Blarg, and group by the result. Something like this:

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

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

using (AdventureWorksDataContext db = new AdventureWorksDataContext())
{
    var result = db.Products.GroupBy(groupExpression).ToList();
    // Throws ArgumentException: "The argument 'value' was the wrong type. 
    //  Expected 'System.Delegate'. 
    //  Actual 'System.Linq.Expressions.Expression`1[System.Func`2[LINQ_Test.Product,System.String]]'."
}

显然 groupEx pression 不正确(请参阅该异常的code注释),但我不知道我应该怎么做。我以为我说的是您可以通过 product.Blarg ,执行它,并返回字符串结果防爆pression。我想这不是我居然说有,但。我还在试图找出EX pression树。任何想法如何,我可以把这事办成?

Obviously groupExpression is incorrect (see the code comment for the exception), but I'm not sure how I should be doing it. What I thought I was saying is "get the Expression from the product.Blarg, execute it, and return the string result." I guess that's not what I'm actually saying there, though. I'm still trying to figure out expression trees. Any idea how I could pull this off?

推荐答案

当你调用防爆pression.Invoke ,第一个参数必须是现有 LambdaEx pression - 它不能是防爆pression LambdaEx pression 。或者换句话说:它是不会来评估 Product.Blarg 每行的,并使用一个不同的子EX pression每次

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);

和通的λ中的参数防爆pression.Invoke ;这里有一个全功能的LINQ到对象的例子,说明这(通过 AsQueryable已()):

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();
    }
}

这篇关于检索防爆pression从属性并将其添加到一个前pression树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆