2010-08-23 23 views
7

Je crée un objet lors de l'exécution à l'aide de l'émission de réflexion. J'ai créé avec succès les champs, les propriétés et les méthodes set. Maintenant, je veux ajouter une méthode. Par souci de simplicité, disons que la méthode renvoie juste un nombre aléatoire. Comment définir le corps de la méthode?Comment créer une méthode lors de l'exécution à l'aide de Reflection.emit

EDIT:

Oui, je l'ai regardé la documentation msdn ainsi que d'autres références et je commence à faire ma tête enroulée autour de ce genre de choses. Je vois comment l'exemple ci-dessus ajoute et/ou multiplie, mais que faire si ma méthode fait autre chose. Comment puis-je définir ce "truc" Supposons que je génère dynamiquement la classe ci-dessous, comment créer le corps de la méthode GetDetails()?

class TestClass 
{ 
    public string Name { get; set; } 
    public int Size { get; set; } 

    public TestClass() 
    { 
    } 

    public TestClass(string Name, int Size) 
    { 
     this.Name = Name; 
     this.Size = Size; 
    } 

    public string GetDetails() 
    { 
     string Details = "Name = " + this.Name + ", Size = " + this.Size.ToString(); 
     return Details; 
    } 
} 

Répondre

15

Vous utilisez un MethodBuilder pour définir des méthodes. Pour définir le corps de la méthode, appelez GetILGenerator() pour obtenir un ILGenerator, puis appelez les méthodes Emit pour émettre des instructions IL individuelles. Il est un exemple sur la documentation MSDN pour MethodBuilder, et vous pouvez trouver d'autres exemples de la façon d'utiliser l'émission de réflexion sur la page Using Reflection Emit:

public static void AddMethodDynamically(TypeBuilder myTypeBld, 
            string mthdName, 
            Type[] mthdParams, 
            Type returnType, 
            string mthdAction) 
{ 
    MethodBuilder myMthdBld = myTypeBld.DefineMethod(
              mthdName, 
              MethodAttributes.Public | 
              MethodAttributes.Static, 
              returnType, 
              mthdParams); 
    ILGenerator ILout = myMthdBld.GetILGenerator(); 
    int numParams = mthdParams.Length; 
    for (byte x = 0; x < numParams; x++) 
    { 
     ILout.Emit(OpCodes.Ldarg_S, x); 
    } 
    if (numParams > 1) 
    { 
     for (int y = 0; y < (numParams - 1); y++) 
     { 
      switch (mthdAction) 
      { 
       case "A": ILout.Emit(OpCodes.Add); 
        break; 
       case "M": ILout.Emit(OpCodes.Mul); 
        break; 
       default: ILout.Emit(OpCodes.Add); 
        break; 
      } 
     } 
    } 
    ILout.Emit(OpCodes.Ret); 
} 

On dirait que vous êtes à la recherche de ressources sur l'écriture MSIL . Une ressource importante est la classe OpCodes, qui a un membre pour chaque instruction IL. La documentation décrit le fonctionnement de chaque instruction. Une autre ressource importante est soit Ildasm ou Reflector. Cela vous permettra de voir l'IL pour le code compilé, ce qui vous aidera à comprendre ce que vous voulez écrire. Exécution de votre GetDetailsMethod par réflecteur et le réglage de la langue IL donne:

.method public hidebysig instance string GetDetails() cil managed 
{ 
    .maxstack 4 
    .locals init (
     [0] string Details, 
     [1] string CS$1$0000, 
     [2] int32 CS$0$0001) 
    L_0000: nop 
    L_0001: ldstr "Name = " 
    L_0006: ldarg.0 
    L_0007: call instance string ConsoleApplication1.TestClass::get_Name() 
    L_000c: ldstr ", Size = " 
    L_0011: ldarg.0 
    L_0012: call instance int32 ConsoleApplication1.TestClass::get_Size() 
    L_0017: stloc.2 
    L_0018: ldloca.s CS$0$0001 
    L_001a: call instance string [mscorlib]System.Int32::ToString() 
    L_001f: call string [mscorlib]System.String::Concat(string, string, string, string) 
    L_0024: stloc.0 
    L_0025: ldloc.0 
    L_0026: stloc.1 
    L_0027: br.s L_0029 
    L_0029: ldloc.1 
    L_002a: ret 
} 

Pour générer une méthode comme dynamique, vous devrez appeler ILGenerator.Emit pour chaque instruction:

ilGen.Emit(OpCodes.Nop); 
ilGen.Emit(OpCodes.Ldstr, "Name = "); 
ilGen.Emit(OpCodes.Ldarg_0); 
ilGen.Emit(OpCodes.Call, nameProperty.GetGetMethod()); 
// etc.. 

Vous pouvez également vouloir chercher des introductions à MSIL, comme celui-ci: Introduction to IL Assembly Language.