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

问题描述:

我在字符串中保存方法体。我想动态地创建方法。但我不知道,如何设置它的身体。我看到使用CodeDom非常乏味的方式。我看到使用OpCodes发射。有没有办法使用字符串变量的现成代码?是否有任何简单的方法来创建方法并在C#中动态设置它的主体?

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 

你需要看看这些命名空间:

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

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

+0

哦,谢谢!文中提供了动态编译的准备课程,您可以参考它。 只需写 ww脚本lo_script = new wwScripting(“CSharp”); lo_script.lSaveSourceCode = true; lo_script.AddAssembly(“mscorlib.dll”); string result =(string)lo_script.ExecuteCode(method_body,new object [] {.../* params */...}); 这是非常方便的方式。 – greatromul 2010-06-13 14:31:08

+0

这种方式可行,但只有在绝对信任输入代码的情况下,才应使用该方法。如果一些最终用户(或者可能是一些可下载的内容)有能力运行代码,那么您应该非常小心。只是一个供参考,所以它不会让你陷入困境。 – drharris 2010-06-15 03:07:13

将其保存到一个.CS文件,并在飞行中编译和执行。

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

  • 使用CSharpCodeProvider,但你必须在加载它作为一种方法(和创建委托给它)通过反射
  • 使用CodeDom
  • 使用Reflection.Emit
  • 使用Expression

在4.0中,Expression API远远富裕比在3.5,允许在没有最常见的结构CodeDom的痛苦。但是不要打折Reflection.Emit - 需要一点时间才能让你的脑袋围绕ILGenerator并使用堆栈,但它并不像人们想象的那么糟糕。

作为一个附注,不要使用InvokeDynamicMethod,除非你只想执行一次。更好的方法是使用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();