依賴反映的 API
在某些情況下,很難察覺程式碼中是否有使用反映,因此 .NET Native 工具鏈不會保留執行階段所需的中繼資料。 本主題涵蓋一些常見的 API 或常見的程式設計模式,這些 API 或程式設計模式不是反映 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" />