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

时间:2010-06-07 05:13:30

标签: c# reflection methods dynamic codedom

我在字符串中保存方法体。我想动态创建方法。但我不知道,如何设置它的身体。我看到使用CodeDom非常乏味。我看到使用Emit和OpCodes。有没有办法从字符串变量中使用现成的代码?

string method_body = "return \"Hello, world!\";"; //there is method body
DynamicMethod dm = new System.Reflection.Emit.DynamicMethod("My_method",
                 typeof(string), new Type[] { }); //any way to create method dynamically
//any way to set body
string result = (string)dm.Invoke(...); //I need write result in variable

3 个答案:

答案 0 :(得分: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();

答案 1 :(得分:1)

将其保存到.CS文件并动态编译并执行。

答案 2 :(得分:1)

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

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

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