3

私は DynamicMethod で遊んでいて、次のことを目指しています:

を使用して IL コードをバイトとして取得するアクションがありますGetILAsByteArray()。このバイトから動的メソッドを作成して実行したいと思います。ここに私がやろうとしていることの例があります:

class Program
{
    static void Main(string[] args)
    {
        //Create action and execute
        Action<string> myAction = s =>
        {
            Console.WriteLine("Hello " + s);
        };
        myAction("World");
        //Get IL bytes
        byte[] ilBytes = myAction.GetMethodInfo().GetMethodBody().GetILAsByteArray();
        DynamicMethod dynamicCallback = new DynamicMethod("myAction", typeof(void), new Type[] { typeof(string) });
        DynamicILInfo dynamicIlInfo = dynamicCallback.GetDynamicILInfo();
        dynamicIlInfo.SetCode(ilBytes, 100);
        dynamicCallback.Invoke(null, new object[] { "World" });
    }
}

を呼び出すと、dynamicCallback.Invoke(null, new object[] { "World" })「例外がスローされました: 'System.BadImageFormatException' in mscorlib.dll」が表示されます。

私が知らないことの1つは、 の2番目の引数として何を使用するSetCode()必要があるか、「maxStackSize」として何を使用する必要があるかです。初期アクションと同じ値を設定するにはどうすればよいですか? しかし、これは例外の理由ではないと思います。

ILバイトから動的メソッドを適切に作成するにはどうすればよいですか?


解決

ここで、Dudi Keleti によって提供された完全なソリューションを要約したいと思います。

static void Main(string[] args)
{
    Action<string> myAction = s =>
    {
        Console.WriteLine("Hello " + s);
    };
    MethodInfo method = myAction.GetMethodInfo();
    object target = myAction.Target;

    DynamicMethod dm = new DynamicMethod(
        method.Name,
        method.ReturnType,
        new[] {method.DeclaringType}.
            Concat(method.GetParameters().
                Select(pi => pi.ParameterType)).ToArray(),
        method.DeclaringType,
        skipVisibility: true);

    DynamicILInfo ilInfo = dm.GetDynamicILInfo();
    var body = method.GetMethodBody();
    SignatureHelper sig = SignatureHelper.GetLocalVarSigHelper();
    foreach (LocalVariableInfo lvi in body.LocalVariables)
    {
       sig.AddArgument(lvi.LocalType, lvi.IsPinned);
    }
    ilInfo.SetLocalSignature(sig.GetSignature());
    byte[] code = body.GetILAsByteArray();
    ILReader reader = new ILReader(method);
    DynamicMethodHelper.ILInfoGetTokenVisitor visitor = new DynamicMethodHelper.ILInfoGetTokenVisitor(ilInfo, code);
    reader.Accept(visitor);
    ilInfo.SetCode(code, body.MaxStackSize);

    dm.Invoke(target, new object[] { target, "World" });

    Console.ReadLine(); //Just to see the result
}

注: DynamicMethodHelper は Haibo Luo によって開発され、ブログ投稿で説明されているクラスですが、ここから直接ダウンロードすることもできます。

4

1 に答える 1