2012-08-22 7 views
3

J'ai créé une méthode dynamique, mais lorsque je tente d'accéder à des ressources extérieures, il me donne une exceptionComment créer une méthode dynamique qui utilise des variables statiques du même assemblage?

TargetInvocationException: Exception a été levée par la cible de une invocation.

Fondamentalement, je veux écrire une méthode pour byte array, puis le charger comme une méthode dynamique. Je sais qu'un simple tableau d'octets n'est pas suffisant pour reconstruire les liens de métadonnées, mais comment faire une méthode dynamique qui utilise une variable du même assemblage?

J'ai essayé de convertir ce code:

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

Ce qui me donne l'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 

Quel est le nombre d'octets:

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

Le Je l'ai testé comme ça:

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 Je souhaite corriger les références d'un tableau d'octets qui représente une IL de méthode dynamique. Comment faire ça? En outre, je ne veux pas utiliser le ILGenerator(), je veux un tableau d'octets.

+0

Vous avez différentes exceptions. Voir 'InnerException'. – Rafal

+0

Avec ILGenerator, j'obtiens: "L'opération n'est pas valide en raison de l'état actuel de l'objet." – blez

+2

Pourriez-vous expliquer dans quel but? –

Répondre

3

Le jeton de métadonnées ne peut pas être réutilisé tel quel; à la place, vous devrez utiliser DynamicILInfo.GetTokenFor pour obtenir un nouveau jeton correspondant au champ que vous pouvez ensuite utiliser. Dans votre cas, cela ressemblerait à quelque chose comme ceci:

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

Cependant, vous aurez probablement besoin aussi de créer vos DynamicMethod de sorte que les contrôles de visibilité JIT sont désactivées, ou votre méthode ne sera pas en mesure d'accéder au champ privé , en tous cas. Sur une note non liée, je ne sais pas ce que vous faites avec les informations sur les signatures - il semble que vous définissiez la signature de la variable locale avec une signature de méthode modifiée pour une raison quelconque ... Je pense que vous devriez faire quelque chose plus comme ceci:

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

Bien sûr, vous aurez besoin de faire varier cette fonction de ce que les habitants de votre méthode utilise réellement.

+0

Il met à jour les index du tableau 'bytes' que vous avez défini, en remplaçant les octets de l'ancien jeton de métadonnées par les octets du nouveau jeton. – kvb

Questions connexes