如何转换表达式树?
更新:
我会尝试解释我的意思。 有 2 个不同类(MyClass1 和 MyClass2)和将 class1 转换为 class2 的方法:
class MyClass1
{
//...Some fields and properties
}
class MyClass2
{
//...Some fields and properties
}
public MyClass2 Convert(MyClass1 class1)
{
//.....
return class2Object;
}
有 2 种不同的方法:
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
}
如何转换 Expression<功能< MyClass1,布尔>>>到表达式<功能< MyClass2,布尔> >
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
让我猜猜您在问什么:您的
MyClass1
和MyClass2
看起来相同(它们都有一个 int field1 和一个 string field2)。现在您有一个Expression>
,类似于:您想要另一个表达式,它看起来相同,但它用于
MyClass2
:如果这就是您所问的问题,这是我的答案:
要获取
MyClass2
的表达式,您需要替换exp1 中的所有
,因为 exp1 中的所有x
x
都是MyClass1
类型。 ExpressionVisitor 正是您想要的。访问者将遍历(称为“访问”)整个表达式,访问所有节点。当涉及到
ParameterExpression
节点时,我们更改该节点(因为它是 MyClass1,所以我们将其更改为 MyClass2,请参阅 VisitParameter 方法)。我们需要改变的另一件事是,当访问者来到像x.field1
这样的节点时,它访问的是MyClass1
中的field1,我们也需要修改它(参见VisitMember )。遍历整个exp1后,我们得到一个全新的exp2,替换了一些节点,这就是我们想要的。Let me guess what you are asking: Your
MyClass1
andMyClass2
look the same (they both have an int field1 and a string field2). Now you have anExpression<Func<MyClass1,bool>>
, something like:And you want another expression, which looks the same, but it's for
MyClass2
:If this is what you are asking, here is my answer:
To get the expression for
MyClass2
, you need to replace allx
inexp1
, because allx
in exp1 are of typeMyClass1
. ExpressionVisitor is exactly what you want.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 likex.field1
, it's visiting the field1 inMyClass1
, 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.表达式树是不可变的,因此要做到这一点,您需要遍历整个树,重建它并用等效项替换该类型的任何使用 - 通常通过编写“访问者”。当遇到 MemberExpression 或 MethodCallExpression 时,您将检查成员的声明类型 - 如果它是您不想要的类型,请重新创建它(Expression.PropertyOrField 在这里很有用)。
请注意,您不能仅在使用它的地方执行此操作;整棵树必须重新生成。我现在不在电脑前,但如果你愿意的话我可以稍后做一个例子;如果您需要此示例,请发表评论。
请注意,由于 int/long 和 char/string 不匹配,这有点复杂。
Expression trees are immutable, so to do this ou would need to walk the entire tree, rebuilding it and substiting any uses of the type with the equivalent - usually by writing a "visitor". When encountering a MemberExpression or MethodCallExpression, you would check the member's declaring type - if it is the one ou don't want, recreate it (Expression.PropertyOrField is useful here).
Note that you can't do this just at the places it is used; the entire tree must be regenerated. I'm not at a PC at the moment, but if you want I can do an example later; leave a comment if you need this example.
Note that this is somewhat complicated by the int/long and char/string mismatch.
您可以将第一个表达式编译为委托,然后使用
NJection.LambdaConverter 将其转换是一个将委托转换为表达式树的库。
You could compile the first expression to a delegate and then convert it with
NJection.LambdaConverter which is a library that converts delegates to expression trees.