2010-08-23 5 views
7

나는 리플렉션을 사용하여 런타임에 객체를 만듭니다. 필드, 속성을 성공적으로 만들고 set 메서드를 가져 왔습니다. 이제 메소드를 추가하고 싶습니다. 간단하게하기 위해 메서드가 난수를 반환한다고 가정 해 봅시다. 방법 본문은 어떻게 정의합니까?Reflection.emit을 사용하여 런타임에 메서드를 만드는 방법

편집 :

예, 다른 참조와 함께 MSDN 설명서에서 찾아 봤는데 내가 내 머리가이 물건을 감싸 얻을 시작 했어. 위의 예제가 추가 및/또는 멀티 플라이 (add/and/multplying) 방법 인 것을 볼 수 있지만, 내 메소드가 다른 것들을하고 있다면 어떻게 될까? 그 "물건"을 정의하는 방법 아래 클래스를 동적으로 생성한다고 가정 할 때, 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; 
    } 
} 

답변

15

MethodBuilder을 사용하면 메소드를 정의 할 수 있습니다. 메서드 본문을 정의하려면 GetILGenerator()을 호출하여 ILGenerator을 가져온 다음 Emit 메서드를 호출하여 개별 IL 명령을 내 보냅니다. 이 MethodBuilder에 대한 MSDN 설명서에 대한 예입니다, 당신은 반사가 Using Reflection Emit 페이지에서 방출 사용하는 방법의 다른 예를 찾을 수 있습니다 : 당신이 MSIL을 작성하는 자원을 찾고있는 것처럼

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

소리가 난다 . 한 가지 중요한 리소스는 모든 IL 명령어에 대한 멤버가있는 OpCodes 클래스입니다. 설명서에는 각 지침의 작동 방식이 설명되어 있습니다. 또 다른 중요한 자원은 Ildasm 또는 Reflector입니다. 이것들은 컴파일 된 코드에 대한 일리노이를 볼 수있게 해 주며, 작성하고자하는 일리노이를 이해하는 데 도움이됩니다. 반사경을 통해 GetDetailsMethod을 실행하고 IL 수익률에 언어 설정 :

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

동적 그런 방법을 생성하기를, 각 명령에 대한 ILGenerator.Emit를 호출해야합니다

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

을 당신은 또한 할 수있다 다음과 같은 MSIL에 대한 소개를 찾고 싶습니다 : Introduction to IL Assembly Language.

관련 문제