2016-01-12 3 views
1

Je voulais essayer comment le System.Reflection.Emit fonctionne, mais finalement j'ai empilé avec un problème. Je voulais créer (en utilisant Emit) une classe simple, comme ceci:C#, reflection.emit essayant dur

using System; 

namespace emit 
{ 
    class Builder 
    { 
     private String name; 

     public Builder(String builderName) 
     { 
      name = builderName; 
     } 

     public override int GetHashCode() 
     { 
      return name.GetHashCode(); 
     } 

     public override string ToString() 
     { 
      return this.name; 
     } 
    } 
} 

Je suis passé par quelques tutoriels et j'ai réussi à créer la bibliothèque dynamique. J'ai sauvegardé cette bibliothèque sur mon disque puis je l'ai chargée en utilisant la réflexion. J'ai été capable de filtrer ses types, constructeurs et méthodes. J'ai également invoqué avec succès le constructeur en passant string désiré. Pourtant, il y a un problème quand j'essaie d'invoquer l'une des méthodes - System.Reflection.TargetInvocationException est lancé.

Voilà comment je GetHashCode() mis en œuvre:

MethodBuilder mHashCode = tBuilder.DefineMethod("GetHashCode", 
       MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, 
       CallingConventions.HasThis, typeof(System.Int32), null); 
      mHashCode.SetImplementationFlags(MethodImplAttributes.Managed); 
      ILGenerator mHashGenerator = mHashCode.GetILGenerator(); 

      MethodInfo defaultHashCode = typeof(object).GetMethod("GetHashCode"); 

      mHashGenerator.Emit(OpCodes.Ldfld, simpleName); 
      mHashGenerator.Emit(OpCodes.Callvirt, defaultHashCode); 
      mHashGenerator.Emit(OpCodes.Ret); 

tBuilder est TypeBuilder que je crée.

Après avoir enregistré l'assemblage et la recherche dans avec ILDSASM il est comme: enter image description here

Et le EditModule.dll: enter image description here

Malheureusement, cette méthode ne sera pas invoquer. Voici le code:

   Type dType = asm.GetTypes()[0]; 
       ConstructorInfo dConstructor = dType.GetConstructor(new Type[] { typeof(string) }); 
       object dObject = dConstructor.Invoke(new object[] { "Pawel" }); 
       MethodInfo[] dMethods = dType.GetMethods(); 
       foreach(var mi in dMethods) 
       { 
        Console.WriteLine(mi.Name); 
       } 
       //method with `0` index is `GetHashCode()` 
       dMethods[0].Invoke(dObject, null); 

Est-ce que quelqu'un a une idée de ce que je pourrais faire de mal?

+0

Quelle est l'exception intérieure du TargetInvocationException? – stuartd

+0

C'est quelque chose comme "CLR Environment a capturé un programme inapproprié". StackTrace montre que 'BuilderEmitType.GetHashCode()' provoque cela. –

Répondre

1

Ce fragment

mHashGenerator.Emit(OpCodes.Ldfld, simpleName); 

tente d'obtenir la valeur du champ, mais vous avez oublié que pour le faire, il a besoin d'un exemple. Étant donné que la méthode que vous construisez est une méthode d'instance, ce est le premier argument caché de la méthode, pour ainsi obtenir la valeur de this.name vous devez utiliser les éléments suivants

mHashGenerator.Emit(OpCodes.Ldarg_0); 
mHashGenerator.Emit(OpCodes.Ldfld, simpleName); 
+0

C'est vrai! Merci, j'ai mal compris le sens de l'énumération "CallingConvention". –