c# - 如何将 Expression.Lambda 附加到任何所有者类型?

标签 c# code-generation expression-trees reflection.emit dynamicmethod

我希望这个测试通过:

[Test]
public void LambdaTest()
{
    var m = Expression.Lambda(typeof(Func<int>), Expression.Constant(0)).Compile();
    Assert.That(m.Method.DeclaringType, Is.Not.Null);
}

这是使堆栈遍历滞后代码正常工作所必需的。最简单的方法是什么?

我更喜欢最便携的方式。

最佳答案

您可以在运行时构建一个新类型,然后将表达式编译成该类型的方法。

您需要在运行时创建一个新程序集和一个新模块。一旦你创建了它们,你就可以使用它们来创建任意数量的类型。下面是创建程序集和模块的代码示例:

var assemblyBuilder =
    AppDomain.CurrentDomain.DefineDynamicAssembly(
        new AssemblyName {Name = "MyNewAssembly"},
        AssemblyBuilderAccess.Run);

var moduleBuilder = assemblyBuilder.DefineDynamicModule("MyNewModule");

现在,您可以使用模块构建器来定义一个新类型,如下所示:

var typeBuilder = moduleBuilder.DefineType("MyNewType"); 

然后像这样的新方法:

var methodBuilder = 
    typeBuilder.DefineMethod(
        "MyNewMethod",
        MethodAttributes.Public | MethodAttributes.Static,
        typeof(int), //returns an int
        new Type[]{}); //takes no parameters

请注意,方法签名应与您的表达式委托(delegate)类型匹配。

接下来,我们使用 CompileToMethod 方法将表达式编译到新方法中:

var expression = Expression.Lambda(typeof(Func<int>), Expression.Constant(0));

expression.CompileToMethod(methodBuilder);

我们从类型构建器生成实际类型:

var type = typeBuilder.CreateType();

然后我们使用 Delegate.CreateDelegate 方法为新创建的静态方法创建委托(delegate),如下所示:

Func<int> func =
    (Func<int>)Delegate.CreateDelegate(
        typeof(Func<int>),
        type.GetMethod("MyNewMethod"));

int value = func(); //Test

现在 func.Method.DeclaringType 将返回我们动态创建的类型。

您可以轻松地使用此代码生成一些辅助方法,使其易于使用。

关于c# - 如何将 Expression.Lambda 附加到任何所有者类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38339570/

相关文章:

c# - 使用自定义方法构造 AndAlso/OrElse LINQ 表达式

c# - 如何使用表达式设置属性和嵌套属性的属性

c# - 如何将字典转换为查找?

c# - Web服务内存泄漏的原因

oop - Matlab 面向对象的组合、聚合

c# - 如何使用 Expression<Func> 设置嵌套属性?

c# - 检测asp :FileUpload has a file using Jquery?

c# - 错误 : Visual Studio 2022 "The build must be stopped before the solution can be closed." Disable Bullid option after build

javascript - 使用后端生成的 Javascript 或 CSS 有什么缺点?

go - Kubernetes 客户端代码生成器 : Can the code exist only locally and not on a repository for the core-generator to work?