4

動的メソッドを作成しましたが、外部リソースにアクセスしようとすると例外が発生します

TargetInvocationException: 呼び出しのターゲットによって例外がスローされました。

基本的には、バイト配列にメソッドを記述し、それを動的メソッドとしてロードしたいと考えています。メタデータ リンクを再構築するには単純なバイト配列では不十分であることはわかっていますが、同じアセンブリの変数を使用する動的メソッドを作成するにはどうすればよいでしょうか。

私はそのコードを変換しようとしました:

public static int z = 10;
public static int sum(int x, int y) {
    return x + y + z;
}

これにより、ILが得られます:

0        L_0000:      ldarg.0      
1        L_0001:      ldarg.1      
2        L_0002:      add          
3        L_0003:      ldsfld       System.Int32 CodeGen.Program::z
4        L_0008:      add          
5        L_0009:      ret  

バイトはどれですか:

02 03 58 7E 06 00 00 04 58 2A

私はそれを次のようにテストしました:

public static int z = 10;

static void Main(string[] args) {

    DynamicMethod sum = new DynamicMethod("sum", typeof(int), new Type[] { typeof(int), typeof(int) });
    var info = sum.GetDynamicILInfo();
    var bytes = new byte[] { 0x02, 0x03, 0x58, 0x7E, 0x06, 0x00, 0x00, 0x04, 0x58, 0x2A }; // { 0x02, 0x17, 0x58, 0x2A }; // this is a code for int sum(int x, int y) { return x + y; }

    info.SetCode(bytes, 8);

    var sig = SignatureHelper.GetMethodSigHelper(CallingConventions.Standard, typeof(int));
    byte[] bsig = sig.GetSignature();
    bsig[0] = 0x7;

    info.SetLocalSignature(bsig);

    int x = (int) sum.Invoke(null, new object[] { 10, 20 });
    Console.WriteLine(x.ToString());
    Console.ReadLine();
}

TL;DR 動的メソッドの IL を表すバイト配列の参照を修正したいと考えています。どうやってするか?また、ILGenerator() を使用したくありません。バイト配列が必要です。

4

1 に答える 1

4

メタデータ トークンをそのまま再利用することはできません。代わりにDynamicILInfo.GetTokenFor、使用できるフィールドに対応する新しいトークンを取得するために を使用する必要があります。あなたの場合、これは次のようになります。

var tok = info.GetTokenFor(typeof(...).GetField("z").FieldHandle);
bytes[4] = tok;    
bytes[5] = tok >> 8;
bytes[6] = tok >> 16;
bytes[7] = tok >> 24;

ただし、JIT 可視性チェックが無効になるように、メソッドを作成する必要がある場合もあります。DynamicMethodそうしないと、いずれにせよ、メソッドがプライベート フィールドにアクセスできなくなります。

無関係なことですが、署名情報で何をしているのかわかりません-何らかの理由でローカル変数署名を変更されたメソッド署名に設定しているようです...もっと何かをすべきだと思います代わりにこのように:

info.SetLocalSignature(SignatureHelper.GetLocalVarSigHelper().GetSignature())

もちろん、メソッドが実際に使用するローカルに基づいて、これを変更する必要があります。

于 2012-08-22T16:47:44.253 に答える