2012-01-31 3 views
1

에 나는 같음을 무시 Reflection.Emit를를 사용하여 동적 프록시를 방출하는 데 필요한 다음 클래스 A를Reflection.Emit 코드는 "base"를 호출합니다. "this"대신에. 부울 필드

public class A 
{ 
    public string Name { get; set; } 
} 

있습니다.

// This class must be generated by Reflection.Emit. 
public class AProxy : A 
{ 
    private bool equalsHasBeenCalled; 

    public override bool Equals(object obj) 
    { 
     if (this.equalsHasBeenCalled) 
     { 
      return base.Equals(obj); 
     } 

     this.equalsHasBeenCalled = true; 

     return CaseInsensitiveComparer.Equals(this, obj); // Demo. 
    } 
} 

그러나, (본 리플렉터) 실제 발전 코드 : 물론

public class AProxy : A 
{ 
    private bool equalsHasBeenCalled; 

    public override bool Equals(object obj) 
    { 
     if (base.equalsHasBeenCalled) 
     { 
      return base.Equals(obj); 
     } 

     base.equalsHasBeenCalled = true; 

     return CaseInsensitiveComparer.Equals(this, obj); 
    } 
} 

요식는 System.FieldAccessException를 (그러한 부재가 존재하지 않기 때문에) 발생. 올바른 것은 this.equalsHasBeenCalled (base.equalsHasBeenCalled 아님)으로 전화하는 것입니다.

I 추가 기능 반사판에 대한 코드를 생성하기 위해 (필드 1 필드 "equalsHasBeenCalled"는 대한의 fieldInfo 임) Reflection.Emit를 사용하고 있습니다 : 아마도

 // Writing body 
     gen.Emit(OpCodes.Nop); 

     // I suspect it has to be around here. 
     gen.Emit(OpCodes.Ldarg_0); 
     gen.Emit(OpCodes.Ldfld, field1); 
     gen.Emit(OpCodes.Ldc_I4_0); 

     gen.Emit(OpCodes.Ceq); 
     gen.Emit(OpCodes.Stloc_1); 
     gen.Emit(OpCodes.Ldloc_1); 
     gen.Emit(OpCodes.Brtrue_S, label25); 
     gen.Emit(OpCodes.Nop); 
     gen.Emit(OpCodes.Ldarg_0); 
     gen.Emit(OpCodes.Ldarg_1); 
     gen.Emit(OpCodes.Call, method2); 
     gen.Emit(OpCodes.Stloc_0); 
     gen.Emit(OpCodes.Br_S, label42); 
     gen.MarkLabel(label25); 

     // ..and probably here also? 
     gen.Emit(OpCodes.Ldarg_0); 
     gen.Emit(OpCodes.Ldc_I4_1); 
     gen.Emit(OpCodes.Stfld, field1); 

     gen.Emit(OpCodes.Ldarg_0); 
     gen.Emit(OpCodes.Ldarg_1); 
     gen.Emit(OpCodes.Call, method3); 
     gen.Emit(OpCodes.Stloc_0); 
     gen.Emit(OpCodes.Br_S, label42); 
     gen.MarkLabel(label42); 
     gen.Emit(OpCodes.Ldloc_0); 
     gen.Emit(OpCodes.Ret); 
+0

그러면이 출력은 어떻게 보입니까? 깨진 decompiler 같은 소리 ... – leppie

+0

Reflection.Emit에 대한 자신의 코드를 보여 주시겠습니까? – leppie

+3

왜 C#에서 필요한 것을 작성하지 않고 IL로 디 컴파일하여 설정 방법을 확인하십시오. 프로젝트에서 이와 같은 작업을 더해야한다면 Castle DynamicProxy를 살펴 보시기 바랍니다. –

답변

3

왜 C#에서 필요한 것을 작성하지 않고 IL로 디 컴파일하여 설정 방법을 확인하십시오. 또한 프로젝트에서 이와 같은 작업을 더해야한다면 Castle DynamicProxy를 살펴 보시기 바랍니다.

+0

가장 좋은 방법이었습니다. 생성 된 IL을보고 나서 생성 된 Reflection.Emit 코드가 올바른 것입니다. "field1"에 대한 FieldBuilder의 인스턴스를 제공해야하는 동안 "field1"에 대한 FieldInfo를 제공 한 것뿐이었습니다. 모든 것이 작동합니다 .IL에서 보니 계몽적이었습니다! –

0

this 키워드는 버그를 트리거링을하여 Reflection.Emit 추가 기능을 사용하여 잘못된 코드를 생성합니다. 실제로 아무 것도하지 않으므로 제거하십시오. equalsHasBeenCalled이 키워드를 사용하여 모호하지 않아야합니다.

+0

허,'this'와'base'는 일리노이에 존재하지 않습니다. – leppie

+0

나는 그것을 제거하려고 노력했지만 여전히 .. –

+0

@leppie 나는 그의 첫 번째 예제에서 일리노이로 코드를 컴파일 한 후 reflection.emit 코드를 생성하기 위해 add를 사용한다고 가정했다. –