我需要动态生成一些类型。生成的类型有几个方法,构造函数,实现一个接口并定义静态构造函数。有没有可以帮助完成任务的工具?
我知道反射器的这个插件,但它只在方法级别有用,而我必须生成一个完整的类型。
有Run#,但它处于 pre-alpha 阶段,此外,我想要一个在离线模式下工作的独立工具,这样我就可以将 reflect.emit 指令复制粘贴到生产代码中。
好吧,我个人已经在类上创建了与操作码同名的扩展方法ILGenerator
,并使用了正确的参数,这样我就不必一直查找文档了。这些扩展方法还返回调用它的生成器对象,因此我可以进行调用链。
例如,要实现 ToString 方法,我可以这样做:
var il = method.GetILGenerator();
il
.ldarg_0()
.ldfld(nameField)
.ret();
我还创建了一个类似的类,名为 IL,它具有返回 IL.Element 对象的方法,我可以在最终发出代码之前将其收集到一个集合或类似的对象中,进行操作等。这使我能够创建“代码生产者”而不仅仅是“代码发射器”。细微的差别,但我发现“给我我能发出的代码”比“把代码发出到这个 ILGenerator 中”更有用。
因此,我可以这样做:
IL.Element[] il = new IL.Element[] {
IL.ldarg_0(),
IL.ldfld(nameField),
IL.ret()
};
接着:
method.GetILGenerator.Emit(il); // also an extension method
当然,我还添加了一些额外的扩展方法,使我更容易发出代码,例如“call_smart”,它根据方法的类型(静态、虚拟、 ETC。)。
除此之外,我不知道任何其他工具,所以也许我没有真正回答你的问题。
是的!
System.Linq.Expressions命名空间(在.NET 3.5 中)通过使用抽象表达式树而不是原始 IL,极大地简化了动态生成代码。
这是我从MSDN Expression Trees 页面中偷来的一个示例,只是为了展示它的强大功能:
ParameterExpression numParam = Expression.Parameter(typeof(int), "num");
ConstantExpression five = Expression.Constant(5, typeof(int));
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);
Expression<Func<int, bool>> lambda1 =
Expression.Lambda<Func<int, bool>>(
numLessThanFive,
new ParameterExpression[] { numParam });
但是你不能创建类型,只能创建函数,所以如果你想创建整个类,你将不得不将它与 Reflection.Emit 结合起来。
我喜欢 Reflector 的反射发射语言插件。这使您可以反编译您知道的代码并查看制作它所需的 SRE 代码,非常有用。