API-интерфейсы, основанные на отражении
В некоторых случаях использование отражения в коде не очевидно, поэтому цепочка инструментов .NET Native не сохраняет метаданные, необходимые во время выполнения. В этом разделе рассматриваются некоторые общие интерфейсы API или распространенные шаблоны программирования, которые не считаются частью API-интерфейса отражения, однако используют отражение для успешного выполнения. При их использовании в исходном коде можно добавить сведения о них в файл директив среды выполнения (. rd.xml), чтобы вызовы этих интерфейсов API не создавали исключений MissingMetadataException или других исключений во время выполнения.
Метод Type.MakeGenericType
Можно динамически создать экземпляр универсального типа AppClass<T>
путем вызова метода Type.MakeGenericType с помощью следующего кода:
var t = Type.GetType("App1.AppClass`1", true);
Type[] typeArgs = {typeof(int)};
Type t2 = t.MakeGenericType(typeArgs);
Activator.CreateInstance(t2);
Для успешной работы кода во время выполнения необходимы несколько элементов метаданных. Во-первых, метаданные Browse
для универсального типа без экземпляров, AppClass<T>
:
<Type Name="App1.AppClass`1" Browse="Required PublicAndInternal" />
Это позволяет вызову метода Type.GetType(String, Boolean) завершиться успешно и вернуть допустимый объект Type.
Но даже при добавлении метаданных для универсального типа без экземпляров вызов метода Type.MakeGenericType приводит к исключению MissingMetadataException:
Эта операция не может быть выполнена как метаданные для следующего типа, была удалена по соображениям производительности:
App1.AppClass`1<System.Int32>
.
Можно добавить следующую директиву времени выполнения в файл директив среды выполнения, чтобы добавить метаданные Activate
для конкретного экземпляра, созданного над AppClass<T>
из System.Int32:
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32"
Activate="Required Public" />
Для каждого отдельного экземпляра AppClass<T>
требуется отдельная директива, если она создается с Type.MakeGenericType помощью метода и не используется статически.
Метод MethodInfo.MakeGenericMethod
Определенный класс Class1
с универсальным методом GetMethod<T>(T t)
, GetMethod
можно вызывать с помощью отражения, используя следующий код:
Type ct = typeof(Class1);
MethodInfo mi = ct.GetMethod("GetMethod");
Type[] typeArgs = {typeof(int)};
object[] parameters = { 12 };
var method = mi.MakeGenericMethod(typeArgs);
Class1 c = new Class1();
method.Invoke(c, parameters);
Для успешного выполнения этого кода необходимо несколько элементов метаданных:
Метаданные
Browse
для типа, метод которого необходимо вызвать.Метаданные
Browse
для метода, который требуется вызвать. Если это открытый метод, добавление открытых метаданныхBrowse
для содержащего типа включает и сам метод.Динамические метаданные для вызываемого метода, чтобы делегат вызова отражения не был удален цепочкой инструментов .NET Native. В случае отсутствия динамических метаданных для метода создается следующее исключение MethodInfo.MakeGenericMethod, когда вызывается метод:
MakeGenericMethod() cannot create this generic method instantiation because the instantiation was not metadata-enabled: 'App1.Class1.GenMethod<Int32>(Int32)'.
Следующие директивы среды выполнения гарантируют доступность всех необходимых метаданных:
<Type Name="App1.Class1" Browse="Required PublicAndInternal">
<MethodInstantiation Name="GenMethod" Arguments="System.Int32" Dynamic="Required"/>
</Type>
Директива MethodInstantiation
обязательна для каждого отдельного экземпляра метода, который вызывается динамически, а элемент Arguments
обновляется для отображения аргумента каждого отдельного экземпляра.
Методы метода Array.CreateInstance и Type.MakeTypeArray
В следующем примере вызываются методы Type.MakeArrayType и Array.CreateInstance на типе Class1
.
Type t = typeof(Class1);
Type at = t.MakeArrayType(1);
Array arr = Array.CreateInstance(at, 10);
При отсутствии метаданных массива возникает следующая ошибка:
This operation cannot be carried out as metadata for the following type was removed for performance reasons:
App1.Class1[]
Unfortunately, no further information is available.
метаданные Browse
для типа массива требуются для динамического создания его экземпляра. Следующая директива среды выполнения позволяет создать динамический экземпляр Class1[]
.
<Type Name="App1.Class1[]" Browse="Required Public" />