如何转换表达式树?

Ale*_*dre 1 .net c# lambda

更新:

我会试着解释一下我的意思.有2个不同的类(MyClass1和MyClass2)以及将class1转换为class2的方法:

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

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

public MyClass2 Convert(MyClass1 class1)
{
//.....
return class2Object;
}
Run Code Online (Sandbox Code Playgroud)

有两种不同的方法:

   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
    }
Run Code Online (Sandbox Code Playgroud)

如何转换表达<Func键< MyClass1的,布尔>>以表达<Func键< MyClass2,布尔>>

Che*_*hen 6

让我猜猜你问:你MyClass1MyClass2 看起来一样(它们都具有一个int FIELD1和一个字符串域2).现在你有一个Expression<Func<MyClass1,bool>>,像:

Expression<Func<MyClass1, bool>> exp1 = x => x.field1 == 100; // x is MyClass1
Run Code Online (Sandbox Code Playgroud)

你想要另一个看起来相同的表达式,但它适用于MyClass2:

Expression<Func<MyClass2, bool>> exp2 = x => x.field1 == 100; // x is MyClass2
Run Code Online (Sandbox Code Playgroud)

如果这是你要问的,这是我的答案:

要获取表达式MyClass2,需要替换all xin exp1,因为xexp1中的所有类型都是类型MyClass1.ExpressionVisitor正是您想要的.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

访问者将通过(说"访问")整个表达式,访问所有节点.当谈到ParameterExpression节点时,我们更改节点(因为它是MyClass1,我们将其更改为MyClass2,请参阅VisitParameter方法).我们需要改变的另一件事是,当访问者来到一个节点时x.field1,它正在访问field1 MyClass1,我们也需要修改它(参见VisitMember).经过整个exp1之后,我们得到了一个全新的exp2,取代了一些节点,这就是我们想要的.

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
Run Code Online (Sandbox Code Playgroud)

  • @Alex然后如何描述你的意思? (2认同)