[英]How to insert CIL code to C#
是否可以将IL代码插入C#方法?
我刚发布了一个实用程序 ,它允许整个C#函数体使用自定义属性自动替换为内联IL。 与类似的实用程序一样,这可以通过ILDASM / ILASM往返进行,可以将其设置为构建后步骤。 该工具还调整PDB,以便在调试器中的单个IL指令上保留单步执行和设置断点。 它与其他一些往返IL内联器的不同之处在于它(仅)替代整个函数体,如下所示:
class MyClass
{
[ILFunc(@"
.locals init ([0] int32 i_arg)
ldc.i4.3
ret
")]
int MyFunc(int i_arg)
{
return 3;
}
};
对于高度性能关键的方法,我尝试使用DynamicMethod
来改进编译器生成的IL,但发现由于委托调用开销而导致的好处丢失了。 假设没有您真正需要DynamicMethod
运行时自定义,内联IL给出了手动调整IL的优势而没有命中。
DynamicMethod是在运行时完成此任务的轻量级方法。
Microsoft C#编译器不支持在编译时注入IL,但代码编织工具可以作为后编译步骤。
您需要的工具称为Cecil ,是Mono项目的一部分。
您可以在此处获得有关它的更多信息: http : //www.mono-project.com/Cecil
引自上面的网站:
Cecil是由Jb Evain( http://evain.net/blog/ )编写的库,用于生成和检查ECMA CIL格式的程序和库。 它完全支持泛型,并支持一些调试符号格式。
用简单的英语,使用Cecil,您可以加载现有的托管程序集,浏览所有包含的类型,动态修改它们并将修改后的程序集保存回磁盘。
我将自己的工具添加到此处已提供的解决方案列表中: InlineIL.Fody 。
这使用Fody组装编织工具在构建时修改组件。 这意味着你要做的就是安装一个NuGet包,在你的项目中添加一个配置文件,你就完成了。
然后,您将获得一个简单且类型安全的API来发出IL指令,您可以将其与C#代码混合使用。 我认为用这种方式编写IL比写文本更容易,而且它比ILGenerator
更方便,因为每个操作码只有相关的重载才能获得自己的方法。
这是一个例子, using static InlineIL.IL.Emit;
:
public static void ZeroInit<T>(ref T value)
where T : struct
{
Ldarg(nameof(value));
Ldc_I4_0();
Sizeof(typeof(T));
Unaligned(1);
Initblk();
}
这显示了如何访问C#当前未公开的initblk
指令。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.