Почему вызов DynamicMethod с экземпляром моего собственного класса вызывает исключение? - PullRequest
2 голосов
/ 09 февраля 2010

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

Я пытаюсь создать функцию, которая просто печатает очень простой класс, который я определил. Скажем, если я изменил свой код на печать string s, он работает, но он всегда не запускается, когда я передаю экземпляр моего класса 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();
    }
}

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

Ответы [ 3 ]

1 голос
/ 09 февраля 2010

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

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

0 голосов
/ 09 февраля 2010

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

0 голосов
/ 09 февраля 2010

Первый - вы не должны выдавать код операции Box, поскольку A является классом и его не нужно помещать в коробку. Бокс только для типов значений.

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

...