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" />

См. также раздел