Можно ли вызвать внутренний метод из динамического метода в .NET?

Я пытаюсь вызвать внутренний метод из динамически сгенерированного. Код il прост: ldarg_0, callvirt, ret.

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

Когда я думаю об этом, это кажется логичным, потому что сборка узла динамического метода не является другом сборке объявления типа метода.

Однако я ожидал, что динамический метод по-прежнему будет работать, как и Delegate.CreateDelegate. В конце концов, мне удалось получить MethodInfo внутреннего метода, поэтому барьер разрешений остался позади.

В любом случае, вопрос в том, «можно ли вызвать внутренний метод из динамически сгенерированного?»

Спасибо.

РЕДАКТИРОВАТЬ:

Вот простой пример кода, демонстрирующий проблему:

using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;

namespace A
{
  internal class Data
  {
    internal string String { get; set; }
  }

  public static class Program
  {
    public static void Main()
    {
      Expression<Func<Data, string>> expr = x => x.String;
      var getterInfo = ((PropertyInfo)((MemberExpression)expr.Body).Member).GetGetMethod(true);
      var getter1 = (Func<Data, string>)Delegate.CreateDelegate(typeof(Func<Data, string>), getterInfo);
      var dm = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object) });
      var gen = dm.GetILGenerator();
      gen.Emit(OpCodes.Ldarg_0);
      gen.Emit(OpCodes.Castclass, typeof(Data));
      gen.Emit(OpCodes.Callvirt, getterInfo);
      gen.Emit(OpCodes.Ret);
      var getter2 = (Func<object, object>)dm.CreateDelegate(typeof(Func<object, object>));

      var data = new Data() { String = "Hello" };
      var str1 = getter1(data);
      var str2 = getter2(data);
    }
  }
}

В коде я создаю два делегата открытого экземпляра для доступа к свойству экземпляра Data.String:

  • введите безопасный getter1, используя Delegate.CreateDelegate
  • введите unsafe getter2, используя DynamicMethod

Типобезопасный делегат, созданный Delegate.CreateDelegate, работает, в то время как тот, который использует DynamicMethod, не работает с TypeLoadException.

Обратите внимание, что я не хочу использовать подход, безопасный для типов, поскольку контекст, в котором создается геттер, не является универсальным. Конечно, я могу решить эту проблему, но теперь вопрос стоит принципиальный - почему DynamicMethod не работает там, где успешно Delegate.CreateDelegate?


person mark    schedule 22.11.2009    source источник
comment
Исключение TypeLoadException означает, что сборка не может быть найдена - что говорит программа просмотра журнала слияния?   -  person Jeremy McGee    schedule 22.11.2009
comment
Журнал сварки пуст. С загрузкой сборки проблем возникнуть не должно. Все задействованные сборки находятся в одной папке.   -  person mark    schedule 22.11.2009
comment
@JeremyMcGee прав. Получите список загруженных сборок в AppDomain в режиме отладки и проверьте, есть ли там целевая сборка. Также лучше поместить сюда свой код для проверки.   -  person Mehdi Golchin    schedule 22.11.2009
comment
Добавлен простой пример кода. Спасибо, парни.   -  person mark    schedule 22.11.2009


Ответы (1)


Будет работать, если пропустить проверки видимости.

Измените эту строку

var dm = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object) }, true);

См. msdn: (в частности, таблицу с все норм.)

Это из документа о конструкторе.

limitedSkipVisibility Тип: System.Boolean true, чтобы пропустить JIT-проверки видимости для типов и членов, к которым обращается MSIL динамического метода, со следующим ограничением: уровень доверия сборок, содержащих эти типы и члены, должен быть равен доверию или меньше него. уровень стека вызовов, излучающего динамический метод; в противном случае - ложь.

person Sam Saffron    schedule 22.11.2009
comment
DynamicMethod не входит в стандарт .net, как это сделать в стандарте .net? - person trampster; 11.03.2017