Reflection.Emit与CodeDOM

LBu*_*kin 50 .net c# code-generation codedom reflection.emit

使用Reflection.Emit库与CodeDOM在运行时动态生成代码有什么优缺点?

我试图在基于XML格式运行时可用元数据的系统中生成一些(相对复杂的)动态类.我将生成扩展应用程序集中现有类的类,实现其他接口,添加方法以及覆盖虚拟和抽象成员.

我想确保在深入实现之前选择适当的技术.有关这些不同代码生成技术如何不同的任何信息都会有所帮助.此外,任何有关简化或简化工作的开源库的信息都将是有用的.

Tom*_*cek 60

我认为关于CodeDOM和Reflection.Emit的关键点如下:

  • CodeDom生成C#源代码,通常在生成代码时使用,作为解决方案的一部分并在IDE中编译(例如,LINQ to SQL类,WSDL,XSD都以这种方式工作).在这种情况下,您还可以使用部分类来自定义生成的代码.效率较低,因为它生成C#源,然后运行编译器来解析它(再次!)并编译它.您可以使用相对高级的构造(类似于C#表达式和语句)(如循环)生成代码.

  • Reflection.Emit生成一个IL,因此它直接生成一个程序集,该程序集也只能存储在内存中.因此效率更高.您必须生成低级IL代码(值存储在堆栈中;循环必须使用跳转实现),因此生成更复杂的逻辑有点困难.

通常,我认为Reflection.Emit通常被认为是在运行时生成代码的首选方法,而在编译时生成代码时首选CodeDOM.在您的场景中,它们都可能正常工作(尽管CodeDOM可能需要更高的权限,因为它实际上需要调用C#编译器,这是任何.NET安装的一部分).

另一种选择是使用Expression该类.在.NET 4.0中,它允许您生成与C#表达式和语句等效的代码.但是,它不允许您生成类.因此,您可以将它与Reflection.Emit相结合(以生成将实现委托给使用的代码生成的类Expression).对于某些场景,您可能也不需要完整的类层次结构 - 通常是动态生成的委托的字典,例如Dictionary<string, Action>可能足够好(但当然,这取决于您的确切场景).


Tim*_*son 16

针对CodeDom的代码往往更容易维护,因为您生成C#代码而不是IL(更多人可以读取C#而不是IL).此外,如果您的CodeDom代码出错,则会出现编译错误; 如果您生成无效的IL,则会出现致命异常或崩溃.

但是,因为CodeDom调用csc.exe编译器,所以准备好使用代码会慢一点.使用Reflection.Emit,您可以直接在内存中生成代码.

CodeDom可能适用于大多数事情; 在XmlSerializer与设计师的WinForms使用它.


Vla*_*lad 7

你可能想看一下ExpandoObject.但它只是.NET 4.0.