今天翻閱msdn時看到一個概念Domain Neutral Assemblies,雖然這個咚咚的名字字面意思挺清楚,但是之前從未接觸過,於是特意搜尋了一番,東拉西扯之下,也學到了一些關於App Domain的有趣的東西,在這裡總結記錄一下。
首先,App Domain是什嗎?MSDN裡給出了一堆文字來說明。其實簡單的說,App Domain就是是一個輕量級的進程。
- Domain Neutral Assemblies
顧名思義,Domain Neutral Assemblies就是不跟特定App Domain相關而可以跨越多個App Domains的Assembly。大家都知道,一般情況下,我們自己建立App Domain都是為了動態載入/卸載一些Assemblies,但是Domain Neutral Assemblies比較特殊,它是不能隨著App Domain被unload的。而且處於效能的考慮,Domain Neutral Assemblies只會被JIT一次,JIT之後的代碼會儲存在Share Domain中。但是Assemblies相關的資料依然會儲存在每個載入它的App Domains中。例如:某個Application中有幾個App Domains,而Assembly A被作為一個Domain Neutral Assembly載入。A中有一個類型T,T有一個靜態變數S,那麼T.S在每個App Domain中的值是分別儲存的,修改一個App Domain中的T.S不會改變另一個App Domain中的T.S。
就像C++中的friend classes,在.net 2.0中引入了friend assemblies。通過給Assembly A設定InternalsVisibleToAttribute屬性來設定B是A的Friend Assembly。這樣B中的類型就可以訪問A中的internal類型和internal成員(方法/屬性/子段/事件等)。
- 如何載入Assemblies到一個App Domain
.net提供了多種方法載入一個Assembly到App Domain,但是推薦使用Assembly.Load方法來做這件事。剩下的方法還有:Assembly.LoadFrom, Assembly.ReflectionOnlyLoad, Assembly.ReflectionOnlyLoadFrom。還有一些看起來跟載入Assembly無關的方法,其實也有載入Assembly的副作用,比如Type.GetType, AppDomain.CreateInstance, AppDomain.CreateInstanceAndUnwrap。比較特別的一個方法是AppDomain.Load,這個方法是不推薦在Managed Code中調用的。因為如果你在App Domain A中調用了App Domain B的Load方法,B.Load其實是將Assembly載入到了App Domain B中,這還不是最糟糕的,最糟糕的是,AppDomain的Load方法會返回Assembly的引用到A,還記得吧,App Domain之間是隔離的,A並不能直接調用B中的方法和類型而是要通過Marshal的方式來通訊,但是由於Assembly不是從MarshalByRef繼承,所以Assembly對象必須以Marshal by value的方式返回到A中,這時A會再次根據自己的配置來定位和載入這個Assembly,最好的情況下就是B和A都載入了這個Assembly,如果運氣不好,A和B設定的搜尋路徑不同而A恰好找不到這個Assembly,boom,一個FileNotFoundException就被拋出啦。
通過Assembly的ReflectionOnlyLoad/ReflectionOnlyLoadFrom方法可以把一個Assembly載入到Reflection-Only context中,顧名思義,在這個上下文中的Assembly只能用於反射而不能用於執行。通過這個方法可以載入不同CLR版本的Assembly,我想著名的Reflector應該就是用的這種辦法吧。唯一一個例外就是mscorlib,即使用ReflectionOnlyLoad也是無法載入不同CLR版本的mscorlib。參考資料:http://blogs.msdn.com/junfeng/archive/2004/08/05/208375.aspxhttp://blogs.msdn.com/cbrumme/archive/2003/06/01/51466.aspxhttp://msdn.microsoft.com/en-us/library/43wc4hhs.aspx