Генерируемые отражением и универсальные типы
У меня есть еще один неприятный момент с 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
Итак, вопросы:
- Как определить, безопасен ли тип для вызова
GetMethods()
а похожие методы на? - Как получить фактический список методов и их общие значения аргументов, если тип небезопасен?
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, то это небезопасно.
Как получить фактический список методов и их общие значения аргументов, если тип небезопасен?
Я отошлю вас к документации снова. Фактически выведите тип в сборку, а затем извлеките его из сборки.