Подтвердить что ты не робот

Сгенерированные отражением и общие типы

У меня есть еще один неприятный момент с Reflection.Emit и типом управления.

Скажем, у меня есть тип с именем MyType, который определен в динамически сгенерированной сборке. Вызов MyType.GetMethods() приводит к NotSupportedException, что привело меня к написанию моего собственного набора оберток и поисковых таблиц. Тем не менее, то же самое происходит, когда я вызываю GetMethods() или любые другие методы интроспекции стандартных типовых типов, которые используют мои собственные типы в качестве общих аргументов:

  • Tuple<int, string> = > отлично работает
  • Tuple<int, MyType> = > исключение

Я могу получить список методов из определения общего типа:

typeof(Tuple<int, MyType).GetGenericTypeDefinition().GetMethods()

Однако у методов есть общие заполнители вместо фактических значений (например, T1, TResult и т.д.), и мне не хочется писать еще один kludge, который отслеживает общие аргументы обратно к их исходным значениям.

Образец кода:

var asmName = new AssemblyName("Test");
var access = AssemblyBuilderAccess.Run;
var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, access);
var module = asm.DefineDynamicModule("Test");

var aType = module.DefineType("A");
var tupleType = typeof(Tuple<,>);
var tuple = tupleType.MakeGenericType(new [] { typeof(int), aType });

tuple.GetProperty("Item1"); // <-- here the error

Итак, вопросы:

  • Как определить, безопасен ли тип для вызова GetMethods() и аналогичных методов?
  • Как получить фактический список методов и их общие значения аргументов, если тип небезопасен?
4b9b3361

Ответ 1

Я получил ответ в следующем вопросе . Класс TypeBuilder имеет кучу статических перегрузок, которые выполняют именно ту вещь:

var genericTuple = typeof(Tuple<,>);
var myTuple = genericTuple.MakeGenericType(typeof(int), myType);
var ctor = TypeBuilder.GetConstructor(myTuple, genericTuple.GetConstructors().First());

Странно, нет перегрузки GetProperty. Однако свойства getters и seters все еще могут быть решены с помощью GetMethod:

var genericGetter = typeof(Tuple<,>).GetProperty("Item1").GetMethod;
var actual = TypeBuilder.GetMethod(myTuple, genericGetter);

Ответ 2

Я расскажу вам о документации:

Определение типа с отражением Emect

в котором говорится

Хотя TypeBuilder является производным от Type, некоторые абстрактные методы, определенные в классе Type, не полностью реализованы в TypeBuilder. Эти методы TypeBuilder вызывают исключение NotSupportedException. Желаемая функциональность может быть получена путем получения созданного типа с использованием Type.GetType или Assembly.GetType и отражения на извлеченном типе.

Итак:

Как определить, безопасен ли тип для вызова GetMethods() и аналогичных методов на?

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

Как получить фактический список методов и их общие значения аргументов, если тип небезопасен?

Я снова передам вам документацию. Фактически испускайте тип в сборку, а затем вытащите его из сборки.