API basate sulla reflection
In alcuni casi, l'uso della reflection nel codice non è scontato, quindi la catena di strumenti .NET Native non conserva i metadati necessari al runtime. In questo argomento vengono illustrati modelli di programmazione o API comuni non considerati parte dell'API di reflection ma basati sulla reflection per una corretta esecuzione. Se vengono usati nel codice sorgente, è possibile aggiungere informazioni su di essi al file di direttive di runtime (.rd.xml) in modo che le chiamate a queste API non generino un'eccezione MissingMetadataException o altre eccezioni al runtime.
Metodo Type.MakeGenericType
È possibile creare dinamicamente un'istanza di un tipo generico AppClass<T>
chiamando il metodo Type.MakeGenericType usando un codice simile al seguente:
var t = Type.GetType("App1.AppClass`1", true);
Type[] typeArgs = {typeof(int)};
Type t2 = t.MakeGenericType(typeArgs);
Activator.CreateInstance(t2);
Per una corretta esecuzione del codice al runtime, sono necessari diversi elementi di metadati. Prima di tutto, sono richiesti metadati Browse
per il tipo generico privo di istanze, AppClass<T>
:
<Type Name="App1.AppClass`1" Browse="Required PublicAndInternal" />
Questo assicura l'esito positivo della chiamata al metodo Type.GetType(String, Boolean) e la restituzione di un oggetto Type valido.
Tuttavia, anche se si aggiungono i metadati per il tipo generico privo di istanze, la chiamata al metodo Type.MakeGenericType genera un'eccezione MissingMetadataException:
Questa operazione non può essere eseguita in quanto i metadati per il tipo seguente sono stati rimossi per motivi di prestazioni:
App1.AppClass`1<System.Int32>
.
È possibile aggiungere la seguente direttiva di runtime al file di direttive di runtime per aggiungere i metadati Activate
per la specifica creazione di un'istanza in AppClass<T>
di System.Int32:
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32"
Activate="Required Public" />
Le singole creazioni di istanze in AppClass<T>
richiedono direttive separate se vengono create con il metodo Type.MakeGenericType e non vengono usate staticamente.
Metodo MethodInfo.MakeGenericMethod
In una classe Class1
con un metodo generico GetMethod<T>(T t)
, GetMethod
può essere richiamato mediante reflection usando un codice simile al seguente:
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);
Per una corretta esecuzione, questo codice richiede diversi elementi di metadati:
I metadati
Browse
per il tipo di metodo da chiamare.I metadati
Browse
per il metodo da chiamare. Se si tratta di un metodo pubblico, l'aggiunta di metadatiBrowse
pubblici per il tipo contenitore include anche il metodo.I metadati dinamici per il metodo da chiamare, in modo che il delegato di chiamata della reflection non venga rimosso dalla catena di strumenti .NET Native. Se i metadati dinamici non sono disponibili per il metodo, viene generata la seguente eccezione quando viene chiamato il metodo MethodInfo.MakeGenericMethod:
MakeGenericMethod() cannot create this generic method instantiation because the instantiation was not metadata-enabled: 'App1.Class1.GenMethod<Int32>(Int32)'.
Le seguenti direttive di runtime assicurano la disponibilità di tutti i metadati necessari:
<Type Name="App1.Class1" Browse="Required PublicAndInternal">
<MethodInstantiation Name="GenMethod" Arguments="System.Int32" Dynamic="Required"/>
</Type>
È necessaria una direttiva MethodInstantiation
per ogni singola creazione di un'istanza del metodo richiamato dinamicamente; l'elemento Arguments
viene aggiornato per riflettere ogni singolo argomento di creazione di un'istanza.
Metodi Array.CreateInstance e Type.MakeTypeArray
Il seguente esempio chiama i metodi Type.MakeArrayType e Array.CreateInstance in un tipo Class1
.
Type t = typeof(Class1);
Type at = t.MakeArrayType(1);
Array arr = Array.CreateInstance(at, 10);
Se non sono presenti i metadati della matrice, si verificano i seguenti errori:
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.
I metadati Browse
per il tipo di matrice sono richiesti per la creazione dinamica di un'istanza. La seguente direttiva di runtime consente la creazione dinamica di un'istanza di Class1[]
.
<Type Name="App1.Class1[]" Browse="Required Public" />