Код DynamicMethod, не поддающийся проверке в .Net 4.0 (найден ref 'this', ожидаемый указатель ref 'f__AnonymousType1')

Использовал это решение для преобразования анонимных типов в словари с помощью Reflection.emit. Работал нормально, пока я не перешел на .Net 4.0 с 3.5.

Теперь я получаю «System.Security.VerificationException: операция может дестабилизировать среду выполнения». ошибка.

Преобразовал анонимно загруженный динамический метод в метод, размещенный в динамической сборке, сохранил его, а затем запустил на нем peverify.exe, чтобы выяснить, что не так.

Получил: [IL]: Ошибка: [DynamicAssemblyExample.dll: MyDynamicType::MyMethod][offs et 0x0000000D][найдена ссылка ('this' ptr) 'MyDynamicType'][ожидаемая ссылка '‹>f__AnonymousType1`3[System.String, System.Int32,System.Byte]'] Неожиданный тип в стеке. [IL]: Ошибка: [DynamicAssemblyExample.dll: MyDynamicType::MyMethod][offs et 0x0000000D] Метод не виден. 2 Ошибки при проверке DynamicAssemblyExample.dll

Код:

    foreach (PropertyInfo property in itemType.GetProperties(attributes).Where(info => info.CanRead))
    {
        // load Dictionary (prepare for call later)
        methIL.Emit(OpCodes.Ldloc_0);

        // load key, i.e. name of the property
        methIL.Emit(OpCodes.Ldstr, property.Name);

        // load value of property to stack
        methIL.Emit(OpCodes.Ldarg_0);
        methIL.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null);

        // perform boxing if necessary
        if (property.PropertyType.IsValueType)
        {
            methIL.Emit(OpCodes.Box, property.PropertyType);
        }

        // stack at this point
        // 1. string or null (value)
        // 2. string (key)
        // 3. dictionary

        // ready to call dict.Add(key, value)
        methIL.EmitCall(OpCodes.Callvirt, addMethod, null);

    }

Есть ли способ разыменовать указатель на фактическое свойство? Или надо как-то лить? Любые указатели?

С Уважением!


person user365004    schedule 05.07.2010    source источник


Ответы (2)


Извините, ребята, ошибся, так как реальный динамический метод создает тип делегата, который действует на экземпляр анонимного (или не анонимного) типа, код Ldarg_0 ищет то, чего нет в этой отладочной реализации.

Поэтому я изменил его на OpCodes.Ldnull.

           var attributes = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;
        foreach (PropertyInfo property in itemType.GetProperties(attributes).Where(info => info.CanRead))
        {
            // load Dictionary (prepare for call later)
            methIL.Emit(OpCodes.Ldloc_0);

            // load key, i.e. name of the property
            methIL.Emit(OpCodes.Ldstr, property.Name);

            // load value of property to stack
            methIL.Emit(OpCodes.Ldnull);

            //methIL.Emit(OpCodes.Castclass, itemType);
            methIL.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null);

            // perform boxing if necessary
            if (property.PropertyType.IsValueType)
            {
                methIL.Emit(OpCodes.Box, property.PropertyType);
            }

            // stack at this point
            // 1. string or null (value)
            // 2. string (key)
            // 3. dictionary

            // ready to call dict.Add(key, value)
            methIL.EmitCall(OpCodes.Callvirt, addMethod, null);

        }

Но после проверки я все еще получаю невидимую ошибку метода. Разве методы получения свойств анонимных типов не видны через отражение?

person user365004    schedule 06.07.2010

Просто предложение, пытались ли вы переписать код, который выдает IL, для фактической записи в словарь, т.е. нет Reflection.Emit ? Могу поспорить, что сгенерированный IL каким-то образом неверен, а не код, который обращается к анонимному типу.

person Igor Zevaka    schedule 06.07.2010
comment
Да, я сделал тест, где я сделал это без размышлений, он выглядел почти так же, за исключением кода операции castclass... что дает мне представление. - person user365004; 06.07.2010
comment
Яя, проблема решена. Мне просто нужно было привести аргумент, и он работает. Верификатор времени выполнения .Net 3.5, очевидно, имеет некоторые дыры. Спасибо за ответ. - person user365004; 06.07.2010