如何在C#中创建自定义System.Linq.Expression类?

时间:2022-09-02 15:13:23

Is it possible to create custom Expression classes? If so, does anyone have any examples? Inheriting from the framework abstract Expression class poses a problem in that its constructor takes an ExpressionType parameter, which is a framework enum type - I obviously cannot customise this!

是否可以创建自定义Expression类?如果是这样,有没有人有任何例子?继承自框架抽象Expression类带来了一个问题,因为它的构造函数采用ExpressionType参数,这是一个框架枚举类型 - 我显然无法自定义它!

Any ideas?

4 个解决方案

#1


With .net 3.5 you can't do this because the Expression constructor takes in an ExpressionType enum value, and you can't add new node types to the enum.

使用.net 3.5,您无法执行此操作,因为Expression构造函数接受ExpressionType枚举值,并且您无法将新节点类型添加到枚举中。

You can't overload an existing node type either, because you can't inherit from any of the "leaf classes" (like BinaryExpression) because they are all sealed.

您也不能重载现有节点类型,因为您无法从任何“叶类”(如BinaryExpression)继承,因为它们都是密封的。

According to the MSDN docs it looks like you can do this in CLR v4, as long as you override the "Reduce" method and use a node type ExpressionType.Extension.

根据MSDN文档,您可以在CLR v4中执行此操作,只要您覆盖“Reduce”方法并使用节点类型ExpressionType.Extension。

#2


This is exactly what the DLR code on codeplex had to do; in the end, they re-created the entire codebase in a different namespace (IIRC), until 4.0 gets shipped.

这正是codeplex上的DLR代码所必须做的;最后,他们在不同的命名空间(IIRC)中重新创建了整个代码库,直到4.0发布。

This doesn't necessarily play nicely with the C# compiler; I honestly haven't tried.

这不一定适合C#编译器;老实说,我没试过。

#3


I don't believe you can extend Expression, but I think you could add in a couple of your extension methods to create expression trees to simplify the generation.

我不相信你可以扩展Expression,但我认为你可以添加几个扩展方法来创建表达式树来简化生成。

For example, maybe you always like to compare 2 strings so you could add an extension method that would return the tree to do the comparison. You can also add an expression that calls a function elsewhere in your code so you could only write expression trees for stuff that absolutely has to be developed that way.

例如,您可能总是喜欢比较2个字符串,因此您可以添加一个扩展方法,该方法将返回树进行比较。您还可以添加一个在代码中的其他位置调用函数的表达式,这样您就只能为那些绝对必须以这种方式开发的东西编写表达式树。

#4


I haven't tried this myself either, but I agree with Scott's statement that this should work in 4.0.

我自己也没有尝试过,但我同意Scott的声明,这应该适用于4.0。

Specifically, the Expression Tree Spec on CodePlex says this about the NodeType property:

具体来说,CodePlex上的表达式树规范说明了NodeType属性:

Derivations of Expression that are not in the common set of nodes in .NET should return node kind Extension

不在.NET的公共节点集中的Expression的派生应该返回节点类型Extension

#1


With .net 3.5 you can't do this because the Expression constructor takes in an ExpressionType enum value, and you can't add new node types to the enum.

使用.net 3.5,您无法执行此操作,因为Expression构造函数接受ExpressionType枚举值,并且您无法将新节点类型添加到枚举中。

You can't overload an existing node type either, because you can't inherit from any of the "leaf classes" (like BinaryExpression) because they are all sealed.

您也不能重载现有节点类型,因为您无法从任何“叶类”(如BinaryExpression)继承,因为它们都是密封的。

According to the MSDN docs it looks like you can do this in CLR v4, as long as you override the "Reduce" method and use a node type ExpressionType.Extension.

根据MSDN文档,您可以在CLR v4中执行此操作,只要您覆盖“Reduce”方法并使用节点类型ExpressionType.Extension。

#2


This is exactly what the DLR code on codeplex had to do; in the end, they re-created the entire codebase in a different namespace (IIRC), until 4.0 gets shipped.

这正是codeplex上的DLR代码所必须做的;最后,他们在不同的命名空间(IIRC)中重新创建了整个代码库,直到4.0发布。

This doesn't necessarily play nicely with the C# compiler; I honestly haven't tried.

这不一定适合C#编译器;老实说,我没试过。

#3


I don't believe you can extend Expression, but I think you could add in a couple of your extension methods to create expression trees to simplify the generation.

我不相信你可以扩展Expression,但我认为你可以添加几个扩展方法来创建表达式树来简化生成。

For example, maybe you always like to compare 2 strings so you could add an extension method that would return the tree to do the comparison. You can also add an expression that calls a function elsewhere in your code so you could only write expression trees for stuff that absolutely has to be developed that way.

例如,您可能总是喜欢比较2个字符串,因此您可以添加一个扩展方法,该方法将返回树进行比较。您还可以添加一个在代码中的其他位置调用函数的表达式,这样您就只能为那些绝对必须以这种方式开发的东西编写表达式树。

#4


I haven't tried this myself either, but I agree with Scott's statement that this should work in 4.0.

我自己也没有尝试过,但我同意Scott的声明,这应该适用于4.0。

Specifically, the Expression Tree Spec on CodePlex says this about the NodeType property:

具体来说,CodePlex上的表达式树规范说明了NodeType属性:

Derivations of Expression that are not in the common set of nodes in .NET should return node kind Extension

不在.NET的公共节点集中的Expression的派生应该返回节点类型Extension