1

Reflection.Emit을 사용하여 동적 어셈블리에서 래퍼 클래스를 생성하려고합니다. 자동 래퍼 생성은 "GoInterfaces"라고하는 새로운 오픈 소스 라이브러리의 일부입니다.이 ExecutionEngineException의 원인은 무엇입니까?

래퍼 클래스는 IEnumerable<string>을 구현하고 List<string>을 래핑합니다. 내 래퍼 클래스에 GetEnumerator를() 메서드를 호출 할 때 나는 ExecutionEngineException를 얻을, 그러나

class List1_7931B0B4_79328AA0 : IEnumerable<string> 
{ 
    private readonly List<string> _obj; 

    public List1_7931B0B4_79328AA0(List<string> obj) 
    { 
     this._obj = obj; 
    } 
    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return this._obj.GetEnumerator(); 
    } 
    public sealed IEnumerator<string> GetEnumerator() 
    { 
     return this._obj.GetEnumerator(); 
    } 
} 

: C#을 측면에서, 그것은이하는 모든이입니다. 그래서 동적 어셈블리를 DLL에 저장하고 그것에 ildasm을 사용했습니다. 다음 코드에 문제가 있습니까?

.class public auto ansi sealed List`1_7931B0B4_79328AA0 
    extends [mscorlib]System.Object 
    implements [mscorlib]System.Collections.Generic.IEnumerable`1<string>, 
       [Loyc.Runtime]Loyc.Runtime.IGoInterfaceWrapper 
{ 
    .field private initonly class 
     [mscorlib]System.Collections.Generic.List`1<string> _obj 

    .method public hidebysig virtual final instance 
      class [mscorlib]System.Collections.Generic.IEnumerator`1<string> 
      GetEnumerator() cil managed 
    { 
     // Code size  12 (0xc) 
     .maxstack 1 
     IL_0000: ldarg.0 
     IL_0001: ldfld  class [mscorlib]System.Collections.Generic.List`1<string> List`1_7931B0B4_79328AA0::_obj 
     IL_0006: call  instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<string>::GetEnumerator() 
     IL_000b: ret 
    } // end of method List`1_7931B0B4_79328AA0::GetEnumerator 


    .method public hidebysig virtual final instance 
      class [mscorlib]System.Collections.IEnumerator 
      System.Collections.IEnumerable.GetEnumerator() cil managed 
    { 
     .override [mscorlib]System.Collections.IEnumerable::GetEnumerator 
     // Code size  12 (0xc) 
     .maxstack 1 
     IL_0000: ldarg.0 
     IL_0001: ldfld  class [mscorlib]System.Collections.Generic.List`1<string> List`1_7931B0B4_79328AA0::_obj 
     IL_0006: call  instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<string>::GetEnumerator() 
     IL_000b: ret 
    } // end of method List`1_7931B0B4_79328AA0::System.Collections.IEnumerable.GetEnumerator 
    ... 

I는 다른 인터페이스, 동일한 서명을 가진 다중 인터페이스 메소드로부터 유도 인터페이스를 비롯한 여러 가지의 각종 랩 테스트 스위트있다. 이 문제가 발생하는 경우에만 IEnumerable<T> 줄 바꿈 시도 할 때입니다. 누구든지 원하면 소스 코드 (2 * .cs 파일, 종속성 없음)를 보내 주시면 기쁩니다.

답변

3

List<T>은 실제로 3 GetEnumerator()이고; 명시 적으로 IEnumerable.GetEnumerator()IEnumerable<T>.GetEnumerator()을 구현하지만 값 형식 인 List<T>.Enumerator 인스턴스를 반환하는 public GetEnumerator() 메서드도 있습니다. 코드에서 해당 메소드를 호출하므로 callret 사이에 box opcode를 삽입해야합니다.

나중에 참조 할 수 있도록 예제 C# 코드를 컴파일하고 Reflector에서보고 자신의 IL과 비교하면 쉽게 이해할 수 있습니다.

일리노이의 또 다른 문제는 명시 적 인터페이스 구현이 공개되어서는 안되며 비공개이어야한다는 것입니다. 또한 몇 가지 사소한 차이점이 있지만 이러한 예외 중 하나라도 예외가 발생하지는 않을 것이라고 생각합니다.

+0

고마워요! csc의 결과물과 비교하는 것은 좋은 생각입니다. – Qwertie

+0

그건 그렇고, 정말로 InvalidProgramException을 가져야하지 않습니까? 검증기가 꺼져있을 수 있습니까? 그렇다면 켜십시오. – Qwertie