如何转换前pression树? [英] How to convert an expression tree?

查看:147
本文介绍了如何转换前pression树?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新

我会尽力解释我的意思。 有2 不同的类(MyClass1的和MyClass2的)和方法,以Class1的转换为Class2的:

I'll try to explain what I mean. There are 2 different classes (MyClass1 and MyClass2) and method to convert class1 to class2:

class MyClass1
  {
        //...Some fields and properties
 }

  class MyClass2
   {
        //...Some fields and properties
  }

public MyClass2 Convert(MyClass1 class1)
{
//.....
return class2Object;
}

有两种不同的方式:

   void method1(Expression<Func<MyClass1, bool>> where, //other parameters)
    {
        //some operations
        //...............

        //need to call method2(Expression<Func<MyClass2, bool>>)
        //   BUT! How do I convert Expression<Func<MyClass1, bool>> 
        //   to Expression<Func<MyClass2, bool>>
    }

    void method2(Expression<Func<MyClass2, bool>> where, //other parameters)
    {
        //some operations
    }

我要如何转换前pression&LT; FUNC&LT; MyClass1的,布尔>>给前pression&LT; FUNC&LT; MyClass2的,布尔>>

How do I convert Expression< Func< MyClass1, bool>> to Expression< Func< MyClass2, bool > >

推荐答案

让我猜猜你是问:你的 MyClass1的 MyClass2的看起来是一样的的(他们都有一个int字段1和一个字符串场2)。现在你有一个防爆pression&LT; Func键&LT; MyClass1的,布尔&GT;&GT; ,是这样的:

Let me guess what you are asking: Your MyClass1 and MyClass2 look the same (they both have an int field1 and a string field2). Now you have an Expression<Func<MyClass1,bool>>, something like:

Expression<Func<MyClass1, bool>> exp1 = x => x.field1 == 100; // x is MyClass1

和你想另一位前pression,其中的看起来是一样的的,但它的 MyClass2的

And you want another expression, which looks the same, but it's for MyClass2:

Expression<Func<MyClass2, bool>> exp2 = x => x.field1 == 100; // x is MyClass2

如果这是你问,我的答复如下:

If this is what you are asking, here is my answer:

要获得EX pression为 MyClass2的,你需要替换所有 X EXP1 ,因为所有的 X 在表达式1的类型为 MyClass1的防爆pressionVisitor 正是你想要的。

To get the expression for MyClass2, you need to replace all x in exp1, because all x in exp1 are of type MyClass1. ExpressionVisitor is exactly what you want.

class MyExpressionVisitor : ExpressionVisitor
{
    public ParameterExpression NewParameterExp { get; private set; }

    public MyExpressionVisitor(ParameterExpression newParameterExp)
    {
        NewParameterExp = newParameterExp;
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        return NewParameterExp;
    }

    protected override Expression VisitMember(MemberExpression node)
    {
        if (node.Member.DeclaringType == typeof(MyClass1))
            return Expression.MakeMemberAccess(this.Visit(node.Expression), 
               typeof(MyClass2).GetMember(node.Member.Name).FirstOrDefault());
        return base.VisitMember(node);
    }
}

参观者将经历(说访问),整个前pression,访问所有的节点。当涉及到一个 ParameterEx pression 节点,我们改变的节点(因为它是MyClass1的,我们把它改为MyClass2的,看到VisitParameter法)。我们需要改变的另一件事是,当游客来到像 x.field1 的一个节点,它的访问中 MyClass1的,我们需要修改它太(见VisitMember)。在经历了整个EXP1,我们得到了一个全新的EXP2,有一些节点代替,这就是我们想要的。

The visitor will go through(say "visit") the whole expression, visit all the nodes. When it comes to an ParameterExpression node, we change the node (because it's MyClass1, we change it to MyClass2, see VisitParameter method). Another thing we need to change is, when the visitor comes to a node like x.field1, it's visiting the field1 in MyClass1, we need to modify it too(see VisitMember). After going through the whole exp1, we get a totally new exp2, with some nodes replaced, that's what we want.

Expression<Func<MyClass1, bool>> exp1 = x => x.field1 == 100;

var visitor = new MyExpressionVisitor(Expression.Parameter(typeof(MyClass2), 
                        exp1.Parameters[0].Name));

var exp2 = Expression.Lambda<Func<MyClass2, bool>>
                (visitor.Visit(exp1.Body), visitor.NewParameterExp);

//the following is for testing
var data = new MyClass2();
Console.WriteLine(exp2.Compile()(data));  //False
data.field1 = 100;
Console.WriteLine(exp2.Compile()(data));   //True

这篇关于如何转换前pression树?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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