1

Reflection.Emit を使用して、動的アセンブリでラッパー クラスを生成しようとしています。自動ラッパー生成は、私が書いている「GoInterfaces」という新しいオープンソース ライブラリの一部です。

ラッパー クラスは を実装IEnumerable<string>してラップしList<string>ます。C# の用語では、これが行うことは次のとおりです。

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

しかし、ラッパー クラスで GetEnumerator() メソッドを呼び出そうとすると、ExecutionEngineException が発生します。そこで、動的アセンブリを 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
    ...

他のインターフェイスから派生したインターフェイスや、同一のシグネチャを持つ複数のインターフェイス メソッドなど、あらゆる種類のものをラップするテスト スイートがあります。IEnumerable<T>この問題が発生するのは、ラップしようとしたときだけです。もしよろしければ、ソース コード (2 つの *.cs ファイル、依存関係なし) を送っていただければ幸いです。

4

1 に答える 1

3

List<T>実際には3つGetEnumerator()の方法があります。とを明示的に実装IEnumerable.GetEnumerator()しますが、値型であるインスタンスを返すIEnumerable<T>.GetEnumerator()パブリックメソッドもあります。コードはそのメソッドを呼び出しているため、との間にオペコードを挿入する必要があります。GetEnumerator()List<T>.Enumeratorboxcallret

将来の参考のために、サンプルのC#コードをコンパイルしてReflectorで確認し、それを自分のILと比較すれば、これは非常に簡単に理解できます。

ILのもう1つの問題は、明示的なインターフェイスの実装をパブリックにするのではなく、プライベートにする必要があることです。他にもいくつかの小さな違いがありますが、これらのいずれも例外を引き起こすとは思いません。

于 2010-06-15T14:21:30.880 に答える