2010-08-23 40 views
7

Yansıma emitini kullanarak çalışma zamanında bir nesne oluşturuyorum. Alanları, özellikleri başarıyla oluşturdum ve set yöntemlerini aldım. Şimdi bir yöntem eklemek istiyorum. Sadelik için, yöntemin sadece rastgele bir sayı döndürdüğünü varsayalım. Yöntem gövdesini nasıl tanımlarım?Yansıma.emit kullanarak çalışma zamanında bir yöntem oluşturma

DÜZENLEME:

Evet, diğer başvurularla birlikte msdn belgelerine bakarak oldum ve ben başım bu şeyler sarılı olsun başlıyorum. Yukarıdaki örneğin nasıl eklendiğini ve/veya çoğaltıldığını görüyorum, ancak yöntemim başka şeyler yapıyorsa ne olur? Ben bu şeyi nasıl tanımlarım? Dinamik olarak aşağıdaki sınıfı oluşturduğumu varsayalım, GetDetails() yönteminin gövdesini nasıl oluşturabilirim?

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; 
    } 
} 

cevap

15

Yöntemleri tanımlamak için MethodBuilder kullanın. Yöntem gövdesini tanımlamak için, bir ILGenerator almak için GetILGenerator()'u arayın ve tek tek IL yönergeleri göndermek için Emit yöntemlerini çağırın. Orada MethodBuilder için MSDN belgelere bir örnektir ve yansıma Using Reflection Emit sayfada yayarlar nasıl kullanılacağına ilişkin diğer örnekleri bulabilirsiniz: Eğer MSIL yazma ile ilgili kaynaklar arıyorsanız gibi

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); 
} 

geliyor . Önemli bir kaynak, her IL talimatı için bir üyesi olan OpCodes sınıfıdır. Belgeler, her bir talimatın nasıl çalıştığını açıklar. Diğer önemli bir kaynak da Ildasm veya Reflector'dur. Bunlar, yazmak istediğiniz IL'yi anlamanıza yardımcı olacak derlenmiş kod için IL'yi görmenizi sağlayacaktır. Reflektör aracılığıyla GetDetailsMethod Koşu ve IL verim dili ayarı:

.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 
} 

dinamik böyle bir yöntemi oluşturmak için, her bir komut için ILGenerator.Emit çağırmak gerekir:

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

Ayrıca may Bu gibi MSIL için tanıtımları aramak istiyorum: Introduction to IL Assembly Language.

İlgili konular