Execute .NET IL code in C#

試著忘記壹切 提交于 2019-12-03 10:58:11

You will need to use the infrastructure in the System.Reflection.Emit namespace. Specifically, you should look at the docs for MethodBuilder.CreateMethodBody which takes an array of bytes representing MSIL instructions. There is a full example there, but below is short snippet of its use. Here, I will create a delegate to the dynamic method as well.

I will note that this is only supported in a very limited way, which is called out in the docs:

This is currently not fully supported. The user cannot supply the location of token fix ups and exception handlers.

The issue is that metadata tokens used in IL to reference types, methods, string literals, etc are resolved at the module level. Thus IL is not completely portable in the sense that you can't take arbitrary, raw IL from a method in one module and just drop it into another method in another module. You need the proper metadata tokens in the new module. However, if you know that your IL contains no metadata tokens you can do it, but this severely limits what you can do with this. (HT: svick, Simon Svensson)

class Program
{
    static void Main(string[] args)
    {
        // opcodes for pushing two arguments to the stack, adding, and returning the result.
        byte[] ilcodes = { 0x02, 0x03, 0x58, 0x2A };
        var method = CreateFromILBytes(ilcodes);
        Console.WriteLine(method(2, 3));
    }

    private static Func<int, int, int> CreateFromILBytes(byte[] bytes)
    {
        var asmName = new AssemblyName("DynamicAssembly");
        var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
        var module = asmBuilder.DefineDynamicModule("DynamicModule");
        var typeBuilder = module.DefineType("DynamicType");
        var method = typeBuilder.DefineMethod("DynamicMethod", 
            MethodAttributes.Public | MethodAttributes.Static, 
            typeof(int), 
            new[] { typeof(int), typeof(int) });
        method.CreateMethodBody(bytes, bytes.Length);
        var type = typeBuilder.CreateType();
        return (Func<int, int, int>)type.GetMethod("DynamicMethod").CreateDelegate(typeof(Func<int, int, int>));
    }
}

Note the use of the RunAndSave option. This will save the dynamic assembly to disk in a temporary location. It may be more desirable to use RunAndCollect which will generate the assembly in memory only and allow it to be collected later when all references to it are dead. However, there are some caveats to so called collectible assemblies, detailed here.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!