Почему я не могу привязать DynamicMethod к экземпляру структуры? - PullRequest
1 голос
/ 27 октября 2011

DynamicMethods позволяет вам указать целевой экземпляр для создаваемого вами делегата.Однако, похоже, что это не работает, когда вы используете тип структуры.Сбой за исключением того, что он не может связываться с этим методом.Является ли ошибка, потому что мой IL не распаковывает целевой экземпляр?

Если я изменю здесь A на класс, он будет работать без проблем.Что я делаю неправильно?(Также, пожалуйста, не предлагайте вызывать Delegate.CreateDelegate для привязки к методу GetType с целевым экземпляром)

Вот пример репродукции:

struct A { }
... //then some where in code::
Func<Type> f = CodeGen.CreateDelegate<Func<Type>>(il=>
    il.ldarga_s(0)
    .constrained(typeof(A))
    .callvirt(typeof(object).GetMethod("GetType"))
    .ret(),
    name:"Constrained",
    target:new A()
);

Примечание: я использую Emitted библиотека для свободного интерфейса для IL.Также вот код для метода CodeGen.

public static class CodeGen
{
    public static TDelegate CreateDelegate<TDelegate>(Action<ILGenerator> genFunc, string name = "", object target = null, bool restrictedSkipVisibility = false)
        where TDelegate:class
    {
        ArgumentValidator.AssertGenericIsDelegateType(() => typeof(TDelegate));
        ArgumentValidator.AssertIsNotNull(() => genFunc);

        var invokeMethod = typeof(TDelegate).GetMethod("Invoke");
        var @params = invokeMethod.GetParameters();
        var paramTypes = new Type[@params.Length + 1];
        paramTypes[0] = target == null ? typeof(object) : target.GetType();
        @params.ConvertAll(p => p.ParameterType)
            .CopyTo(paramTypes, 1);
        var method = new DynamicMethod(name ?? string.Empty, invokeMethod.ReturnType, paramTypes, restrictedSkipVisibility);
        genFunc(method.GetILGenerator());

        return method.CreateDelegate<TDelegate>(target);
    }
}

1 Ответ

0 голосов
/ 28 октября 2011

См. Важное примечание на http://msdn.microsoft.com/en-us/library/74x8f551.aspx,, которое также применимо здесь:

Если метод является статическим (Shared в Visual Basic) и его первый параметр имеет тип Object или ValueType, тогда firstArgument может быть значением тип. В этом случае firstArgument автоматически упаковывается. автоматическая для других аргументов бокс не встречается, как в C # или Вызов функции Visual Basic.

Подразумевается, что первый аргумент вашего динамического метода должен иметь тип object, и вам потребуется выполнить ldarg_0, за которым следует unbox перед выполнением ограниченного вызова.

...