Почему вызов DynamicMethod с экземпляром моего собственного класса вызывает исключение?

StackOverflow https://stackoverflow.com/questions/2225091

Вопрос

Я изучаю CIL, создавая свои собственные функции во время выполнения с помощью Reflection.Emit.Я на самом деле удивлен, насколько легко все было до сих пор, но я столкнулся с чем-то, чего не могу догадаться, и не могу найти ничего относительного в документации.

Я пытаюсь создать функцию, которая просто печатает очень простой класс, который я определил.Если я изменю свой код для печати stringскажем, он работает, но всегда не запускается, когда я передаю экземпляр своего класса A.

Что странно, я могу закомментировать тело своей функции, но оно все равно терпит неудачу с TargetInvocationException.Это должно быть довольно просто, но я не понимаю, в чем дело!

class A
{
    public override string  ToString()
    {
        return "AAA!";
    }
}

class Program
{
    static void Main(string[] args)
    {
        DynamicMethod func = new DynamicMethod("func", null, new Type[] { typeof(A) });

        ILGenerator il = func.GetILGenerator();

        //il.Emit(OpCodes.Ldarg_0);
        //il.Emit(OpCodes.Box, typeof(A));
        //il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(A) }));

        il.Emit(OpCodes.Ret);

        func.Invoke(null, new object[] { new A() });

        Console.Read();
    }
}

Что я делаю так неправильно, что это вызывает исключение?Почему это происходит только с моими занятиями?

Это было полезно?

Решение

Проблема проста, но не очевидна.Для начала не ограничивайте аргумент, как уже указывалось.Но настоящая проблема в том, что класс А не является публичным.Привязка по умолчанию для используемой вами функции Invoke (а не полная) заключается в поиске только общедоступных методов.Поскольку A является закрытым классом, это означает, что он не может найти вашу функцию (удивительно, я знаю) и терпит неудачу.

Другие советы

На самом деле это было довольно глупо.Я потратил на это несколько часов, но когда я последовал совету Лорана Этьембля и создал делегата, полученное мной исключение сообщило мне, что мой класс A не является общедоступным.

Решение:Добавьте публичное ключевое слово перед class A.Работает отлично.я знал это должно было быть что-то безумно простое.

Во-первых, вы не должны испускать Box код операции с тех пор A это класс и его не нужно упаковывать.Упаковка предназначена только для типов значений.

Во-вторых. Причина сбоя заключается в том, что у метода нет разрешения на доступ к классу A (он не является общедоступным).Либо сделай A public ИЛИ Вы можете указать JIT-компилятору пропустить проверки видимости, используя этот конструктор и прохождение true к параметруskipVisibility.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top