有没有简单的方法可以在 C# 中创建方法并动态设置其主体?

问题描述 投票:0回答:3

我将方法的主体存储为字符串,并且我希望动态创建此方法。但是,我不确定如何分配它的主体。我遇到过一种使用 CodeDom 的相当复杂的方法,以及另一种使用 Emit 和 OpCodes 的方法。有没有更简单的方法来利用字符串变量中的现有代码?

string method_body = "return \"Hello, world!\";"; // there is a method body
DynamicMethod dm = new System.Reflection.Emit.DynamicMethod("My_method",
                 typeof(string), new Type[] { }); // some way to create method dynamically
// any way to set body?
string result = (string)dm.Invoke(...); // I need to write result in a variable
c# reflection methods dynamic codedom
3个回答
7
投票

听起来你想要的是“编译器即服务”。这不在 MS .NET 4.0 中,但可能在更高版本中。不过它已经在 Mono 中了。在那之前,可用的选项有:

  • 使用
    CSharpCodeProvider
    ,但您必须通过反射将其作为方法加载(并为其创建委托)
  • 使用
    CodeDom
  • 使用
    Reflection.Emit
  • 使用
    Expression

在 4.0 中,

Expression
API 比 3.5 中丰富得多,允许最常见的构造,而无需经历
CodeDom
的痛苦。但不要低估
Reflection.Emit
- 需要一点时间来了解
ILGenerator
并使用堆栈,但这并不像人们想象的那么糟糕。

作为旁注,不要使用

Invoke
中的
DynamicMethod
除非您只想执行一次。更好的方法是使用
CreateDelegate
,然后存储(并重新使用)该委托:

var dm = new System.Reflection.Emit.DynamicMethod("My_method",
    typeof(string), null);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldstr, "Hello, world!");
il.Emit(OpCodes.Ret);
Func<string> func = (Func<string>)dm.CreateDelegate(typeof(Func<string>));
var s = func();

或者使用

Expression
API:

var lambda =Expression.Lambda<Func<string>>(Expression.Constant("Hello, world"));
var func = lambda.Compile();
var s = func();

2
投票

您需要查看这些命名空间:

System.Reflection;
System.CodeDom.Compiler;
Microsoft.CSharp;

这可能会让您开始:http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm


1
投票

将其保存到 .CS 文件并即时编译和执行。

© www.soinside.com 2019 - 2024. All rights reserved.