Генерируемые отражением и универсальные типы

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

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

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

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

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

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

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

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's the error

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

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

2 ответа

Решение

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

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

Как ни странно, нет перегрузки GetProperty, Однако методы получения и установки свойств все еще могут быть разрешены с помощью GetMethod:

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

Я отошлю вас к документации:

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

который говорит

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

Так:

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

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

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

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

Другие вопросы по тегам