此系列系小九的學堂原創翻譯,翻譯自微軟官方開發向導,一共分為六個主題。本文是第五個主題:.Net Native與反射。
向導文鏈接:《C++的性能C#的產能?! - .Net Native 系列:開發向導》
[小九的學堂,致力於以平凡的語言描述不平凡的技術。如要轉載,請注明來源:小九的學堂。cnblogs.com/xfuture]
.NET Native與反射
.NET Framework 4.5
小貼士 |
|---|
| 這個主題依賴於預發行的.net native開發者預覽版。下載地址: Microsoft Connect website. 友情提示需要注冊.. |
.NET Framework框架可以通過反射機制來進行元編程(在編譯時完成部分本應在運行時完成的工作,可提高工作效率)。反射可以動態地創建類型的實例,將類型綁定到現有對象,或從現有對象中獲取類型。然后,可以調用類型的方法或訪問其字段和屬性。支持序列化和反序列化,它支持一個對象的字段先被持久化之后再進行恢復。.NET Framework運行時just-in-time編譯器可以基於可用的元數據來生成本地機器碼。
.NET native運行時並不包含JIT編譯器,所以其編譯的機器碼必須是提前生成的。當然有一系列的方法來測試哪些代碼是已經生成的,但是這些規則並不能涵蓋所有的元編程場景。所以需要在運行時提供指令來進行搜索元編程。同時.NET Native並不能將.NET Framework下的私有成員編譯。
下面將介紹如何使用基於反射的API和運行時指令xml文件的配置:
基於反射的API
在一些情況下你並不能得知代碼中使用了反射而且.NET Native工具並不會保留運行時需要的元數據。本主題所涵蓋的API並不能視為反射的API,但他們是基於反射來執行的。如果你使用這些API的話,需要添加一些信息來運行指令.rd.xml文件,這樣就能正常調用這些API,而且不會導致MissingMetadataException的異常。
例如:Type.MakeGenericType method
通過調用這個方法可以在運行時動態生成泛型AppClass<T>
var t = Type.GetType("App1.AppClass`1", true);
Type[] typeArgs = {typeof(int)};
Type t2 = t.MakeGenericType(typeArgs);
Activator.CreateInstance(t2);
為使該代碼能夠成功運行,需要一些元數據支持。首先是在.rd.xml中添加對AppClass<T>的泛型支持
<Type Name="App1.AppClass`1" Browse="Required PublicAndInternal" />
添加后在.NET Framework下就可以調用Type.GetType()方法來獲得對象類型了。
但在.NET Native下調用就會拋出MissingMetadataException的異常。
This operation cannot be carried out as metadata for the following type was removed for performance reasons: App1.AppClass`1<System.Int32>.
你可以在運行時指令文件(.rd.xml)添加下面運行指令來激活對Int32的支持:
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32"
Activate="Required Public" />
不同的實例需要不同的指令,添加后就能正常運行。
類似的方法還有:MethodInfo.MakeGenericMethod method, Array.CreateInstance and Type.MakeTypeArray methods
所以,在依賴反射的方法使用時,需要添加對反射類型的支持的指令才可以使用。
運行時指令文件(.rd.xml)配置
運行時指令文件(.rd.xml)是一個xml配置的文件,指定了配置的程序元素是否可用於反射。下面是該文件的一個樣例。
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Namespace Name="Contoso.Cloud.AppServices" Serialize="Required Public" />
<Namespace Name="ContosoClient.ViewModels" Serialize="Required Public" />
<Namespace Name="ContosoClient.DataModel" Serialize="Required Public" />
<Namespace Name="Contoso.Reader.UtilityLib" Serialize="Required Public" />
<Namespace Name="System.Collections.ObjectModel" >
<TypeInstantiation Name="ObservableCollection"
Arguments="ContosoClient.DataModel.ProductItem" Serialize="Public" />
<TypeInstantiation Name="ReadOnlyObservableCollection"
Arguments="ContosoClient.DataModel.ProductGroup" Serialize="Public" />
</Namespace>
</Application>
</Directives>
文件結構:
該文件在 http://schemas.microsoft.com/netfx/2013/01/metadata 命名空間下。
根元素Directives是指令元素,可以包含一個或者多個Library元素和零個或者一個Application元素,結構如下
Directives [1:1]
Application [0:1]
Assembly [0:M]
Namespace [0:M]
. . .
Type [0:M]
. . .
TypeInstantiation (constructed generic type) [0:M]
. . .
Namespace [0:M]
Namespace [0:M]
. . .
Type [0:M]
. . .
TypeInstantiation (constructed generic type) [0:M]
. . .
Type [0:M]
Type [0:M]
. . .
TypeInstantiation (constructed generic type) [0:M]
. . .
GenericParameter [0:M]
Method [0:M]
Parameter [0:M]
¶ TypeParameter [0:M]
GenericParameter [0:M]
MethodInstantiation (constructed generic method) [0:M]
Property [0:M]
Field [0:M]
Event [0:M]
TypeInstantiation (constructed generic type) [0:M]
Type [0:M]
. . .
TypeInstantiation (constructed generic type) [0:M]
. . .
Method [0:M]
¶ Parameter [0:M]
¶ TypeParameter [0:M]
GenericParameter [0:M]
MethodInstantiation (constructed generic method) [0:M]
Property [0:M]
Field [0:M]
Event [0:M]
Library [0:M]
Assembly [0:M]
Namespace [0:M]
. . .
Type [0:M]
. . .
TypeInstantiation (constructed generic type) [0:M]
. . .
Namespace [0:M]
Namespace [0:M]
. . .
Type [0:M]
. . .
TypeInstantiation (constructed generic type) [0:M]
. . .
Type [0:M]
Type [0:M]
. . .
TypeInstantiation (constructed generic type) [0:M]
. . .
GenericParameter [0:M]
Method [0:M]
MethodInstantiation (constructed generic method) [0:M]
Property [0:M]
Field [0:M]
Event [0:M]
TypeInstantiation (constructed generic type) [0:M]
Type [0:M]
. . .
TypeInstantiation (constructed generic type) [0:M]
. . .
Method [0:M]
MethodInstantiation (constructed generic method) [0:M]
Property [0:M]
Field [0:M]
Event [0:M]
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!-- Child elements go here -->
</Application>
<Library Name="Extensions">
<!-- Child elements go here -->
</Library>
</Directives>
在節點中可以配置需要反射拿到的屬性。具體開發中遇到的反射問題可以參閱之前的一篇文章:C++的性能C#的產能?! - .Net Native 系列《二》:.NET Native開發流程詳解
由於.NET Native是源生的機器碼,它的目的就在於高效率高性能實現.NET Framework架構開發的應用程序的運行,反射消耗性能較多,盡量少用或者更改其他方法來實現邏輯。
更多.rd.xml信息可以參閱:http://msdn.microsoft.com/en-us/library/dn600639(v=vs.110).aspx
希望大家喜歡這項技術,也可以寫下自己對該技術的展望。

小貼士