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

发布于 2024-09-04 11:05:44 字数 496 浏览 1 评论 0原文

我将方法的主体存储为字符串,并且我希望动态创建此方法。但是,我不确定如何分配它的主体。我遇到过一种使用 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

I have the body of a method stored as a string and I'm looking to create this method dynamically. However, I'm unsure how to assign its body. I've come across a rather complex method using CodeDom, and another using Emit with OpCodes. Is there a simpler way to utilize the existing code from a string variable?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

み青杉依旧 2024-09-11 11:05:44

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

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

在 4.0 中,Expression API 比 3.5 中丰富得多,允许大多数常见的构造,而无需 Expression 的痛苦。代码>CodeDom。但不要低估 Reflection.Emit - 需要一些时间来了解 ILGenerator 并使用堆栈,但它并不像人们想象的那么糟糕思考。

附带说明一下,除非您只想执行一次,否则不要使用 DynamicMethod 中的 Invoke。更好的方法是使用 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();

It sounds like what you want is the "compiler as a service". That is not in MS .NET 4.0, but may be in a later release. It is already in Mono, though. Until then, the options available are:

  • use CSharpCodeProvider, but you'll have to load it in as a method (and create a delegate to it) via reflection
  • use CodeDom
  • use Reflection.Emit
  • use Expression

In 4.0, the Expression API is far richer than it was in 3.5, allowing most common constructs without the pain of CodeDom. But don't discount Reflection.Emit - it takes a little while to get your head around ILGenerator and using the stack, but it isn't as bad as people tend to think.

As a side-note, don't use Invoke from DynamicMethod unless you only want to execute it once. The better approach is to use CreateDelegate, then store (and re-use) that delegate:

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();

Or with the Expression API:

var lambda =Expression.Lambda<Func<string>>(Expression.Constant("Hello, world"));
var func = lambda.Compile();
var s = func();
爱的故事 2024-09-11 11:05:44

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

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

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

You need to take a look at these namespaces:

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

This may get you started: http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm

反话 2024-09-11 11:05:44

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

Save this to a .CS file and compile and execute it on the fly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文