Что может вызвать это ExecutionEngineException? - PullRequest
1 голос
/ 15 июня 2010

Я пытаюсь использовать 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 файла, без зависимостей), если кто-то захочет.

1 Ответ

3 голосов
/ 15 июня 2010

List<T> на самом деле имеет 3 GetEnumerator() методов; он явно реализует IEnumerable.GetEnumerator() и IEnumerable<T>.GetEnumerator(), но у него также есть открытый метод GetEnumerator(), возвращающий экземпляр List<T>.Enumerator, который является типом значения. Ваш код вызывает этот метод, и поэтому вам нужно вставить код операции box между call и ret.

Для дальнейшего использования это довольно легко выяснить, если вы просто скомпилируете свой пример кода C #, посмотрите его в Reflector и сравните его с вашим собственным IL.

Другая проблема с вашим IL заключается в том, что ваша явная реализация интерфейса не должна быть публичной, она должна быть закрытой. Есть также несколько других незначительных отличий, но я не думаю, что любое из них могло бы вызвать исключение.

...