程序集和应用程序域
這兩個概念是DotNet程序員經常見到的,但好多人搞不清它們。雖然MSDN對它們有相關的說明,但并不是那么容易看懂。在這里灰灰蟲根據自己的理解用簡單易懂的語言解紹一下它們。
程序集(assembly)
??? “程序集是包含編譯好的、面向.NET Framework的代碼的邏輯單元”
??? 這句話可以理解如下:
??????? 首先:程序集是代碼的邏輯單元,是邏輯上的概念。它不完全等價于編譯好的DLL物理文件,但一般我們認為靜態專用程序集與編譯出的DLL文件或EXE文件是一致的。
??????? 其次:它是被編譯好的。它不是項目名稱或命名空間,更不是源代碼。
??????? 最后:它是是面向.NET Framework的。意味著它雖然被編譯了,但仍需要依托于.NET Framework來運行。
???
??? 一個程序集可以是一個包括元數據的DLL或EXE,也可以由多個文件組成,例如資源文件、元數據、DLL和EXE。
???
??? 注意:Win32的DLL(動態鏈接庫)和DotNet中的DLL(程序集文件)的擴展名雖然都是DLL,但是二者內部的數據組織是不一樣的,所以千萬不要把二者混為一談。
???
??? 程序集的分類:
??????? 靜態程序集和動態程序集:
??????? 靜態程序集:靜態程序集包括中間語言元數據(MSIL,類似于Java字節碼的東西),以及該程序集的資源(位圖、JPEG 文件、資源文件等)。靜態程序集存儲硬盤文件中。
??????? 動態程序集:動態程序集直接從內存運行并且在執行前不存儲到磁盤上,如ASP.NET 2.0中的網站程序運行的時候產生的是動態程序集。
???????
??????? 專用程序集和共享程序集:
??????? 專用程序集一般附帶在某些軟件上,且只為該軟件提供專用的類庫,這些庫包含的代碼只能用于該應用程序。一般專用程序集是與應用程序放在同一目錄下的,在部署的時候與應用程序一起復制到目標機器上即可。
??????? 共享程序集是其他應用程序可以使用的公共庫,一般是安裝到系統GAC中。因為其他軟件可以訪問共享程序集,所以所有共享程序集必須帶有強名稱(由發行者簽名)。
???
??? 本地應用程序目錄可用于存儲專用程序集,所以專用程序集一般不會有版本沖突問題。其他應用程序都不會重寫私有的程序集。當然,仍可以使用私有程序集的版本號,這樣有助于代碼的修改與管理,但它不是.NET所必須的。這種專用程序集是大多數程序員所喜歡的,它可以很好地避免DLL Hell的問題。但這種專用程序集只能部署在應用程序所在的目錄之中,而無法像以往的Win32 DLL那樣放置在System32目錄中供多個應用程序共享,但有的時候設計人員仍有共享程序集的需求(把程序集部署到GAC目錄中),這樣一來又帶來了我們似乎又看到DELL HELL又在慢慢地逼近我們,其實DLL共享程序集中根本不可能出現DELL HELL。因為共享程序集并不是簡單地把私有程序集復制到GAC所在目錄中,開發人員只能使用相關工具把強命名程序集(Strong-name Assembly)放在GAC所在目錄中。在GAC中可以允許同名稱但是不同版本號的程序集存在,當不同版本的強命名程序集安裝在GAC中后,不同的應用程序會根據版本號信息去調用不同的程序集,這樣就不會產生DLL程序集沖突的問題了。
???
??? 幾個概念:
?????? DLL Hell(DLL地獄)
??????????? 在過去Win32程序中,DLL文件可以被安裝在System32目錄中,以供多個應用程序共享。
??????????? 但這種方式給我們帶來了一個新的問題:DLL文件版本控制的問題。如果有兩個軟件共享同一個DLL,那如果其中一個軟件版本升級后把這個DLL文件更新至一個新的版本,那另一個軟件就無法再訪問原來的DLL版本了。如果再安裝第三個軟件,這個軟件也用到了這個DLL,但版本比現有的DLL版本還要低的話,那一旦產生DLL覆蓋后那原有的軟件就有可能不能再用了。這就是通常所說的DLL DELL。
??????
?????? 強命名程序集(Strong-name Assembly)
??????????? 強命名程序集要求設計人員為程序集指定版本號、區域、Private Key等信息,CLR則以此信息來找到正確的程序集。
??????????? 生成Private Key信息:
??????????????? sn -k c:\sgkey.snk??????
??????????? 設置程序集的信息:
??????????? 其中黃色背景部分已過時了。應當如下設置:
??
????????????
?????? GAC(Global Assembly Cache-全局程序集緩存)
??????????? GAC可以緩存全局使用的程序集,大多數共享程序集都安裝在這個緩存中。它對應至硬盤上的一個目錄(C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\GAC),不是所有的程序集文件復制到這個目錄中就可以實現程序集共享的。要放在其中的程序集應當是強命名的程序集,GAC和強命名程序集實現的共享程序集才可以擺脫DLL DELL的困擾。
?????????? 將強命名程序集加載至GAC中:
??????????????? gacutil -i E:\Proj\ClassLibrary831\bin\Debug\ClassLibrary831.dll
??????????? 查看GAC中的所有的程序集:
???????????????? gacutil -l???
??????????? 查看GAC中指定的程序集:
???????????????? gacutil -l ClassLibrary831
??????????? 如果您將組成應用程序的某個程序集置于全局程序集緩存中,則將不再能夠通過使用 xcopy 命令復制應用程序目錄來復制或安裝該應用程序。您還必須在全局程序集緩存中移動該程序集。
???????????
??? 程序集與命名空間的區別:
??????? 一個程序集可以包含個命名空間,一個命名空間也可以跨越多個程序集。
??????? 如果說命名空間是類庫的邏輯組織形式,那么程序集就是類庫的物理組織形式。只有同時指定所在命名空間和所在的程序集,才能完全限定類型。你要使用一個外部的類,必須引用該類所在的程序集,并且導入該類所在的命名空間。
??????? 現在大家應當知道我們在使用某個外部的類時,為什么要在項目中“添加引用”相關的DLL文件,而且還要在代碼中加入using ......了吧?
??? 程序集與項目的區別:
??????? 默認的情況下,項目名稱和程序集的名稱是一致的,但這并不代表二者是一個東西。
??????? 項目是我們開發過程中概念,項目是用來統一管理我們開發過程的源代碼等信息,創建不同的程序,我們應當建立不同的項目來管理。
??????? 程序集是部署與使用中概念,它是我們程序編譯出來的邏輯結果,作為靜態程序集它對應著硬盤上的DLL文件。
??????? 其實我們可以改變程序集的名稱,使它和項目的名稱不一致:
??????? 這樣編譯后,我們發現DLL文件名變為指定的程序集名稱了。
??????? (車延祿)
應用程序域(AppDomain):
??? 在操作系統中,程序和程序之間應實現某種形式的隔離,防止程序和程序之間產生不可預知的影響,這種隔離是必須的。在DotNet技術之前,通常采用進程來形成隔離邊界。每一個應用程序被加載到單獨的進程中,每個進程都有其私有的內存,運行在一個進程中的應用程序不能寫入另一個應用程序的內存,您也不能在兩個進程間進行直接調用。
??? 在.NET結構中,應用程序有一個新的邊界:應用程序域。應用程序域是一個用于隔離應用程序的“輕量級分界線”。所謂的“輕量級”是因為多個應用程序域可以存在于單個操作系統進程中。
??? 應用程序域可以確保在一個域中運行的代碼不會影響進程中的其他應用程序;能夠在不停止整個進程的情況下停止單個應用程序。
??? 進程2321有兩個應用程序域。在應用程序域A中,實例化了對象1和2,對象1在程序集1中,對象2在程序集2中。在進程2322中,第二個應用程序域有實例1。實例和靜態成員不能在應用程序域之間共享,也不能直接訪問另一個應用程序域中的對象。
???
??? AppDomain類用于創建和中斷應用程序域,加載和卸載程序集。
??? 常用屬性和方法:
??????? FriendlyName?? 取得應用程序域的友好名稱
??????? CreateDomain()??? 創建新的應用程序域。
??????? ExecuteAssembly() 執行應用程序域中的程序集。它可用來執行另一個應用程序域中的代碼。
??????? Unload() 執行域的正常卸載。只有應用程序域中正在運行的所有線程都已停止或域中不再有運行的線程之后,才卸載該應用程序域。
??? 創建應用程序域 :
??? class AppDomain1
??? {
??????? public static void Main()
??????? {
???????????? Console.WriteLine("Creating new AppDomain.");
???????????? //創建應用程序域
???????????? AppDomain domain = AppDomain.CreateDomain("MyDomain");??
???????????? //顯示當前應用程序域的友好名稱
???????????? Console.WriteLine("Host domain: " + AppDomain.CurrentDomain.FriendlyName);
???????????? //顯示新建應用程序域的友好名稱
???????????? Console.WriteLine("child domain: " + domain.FriendlyName);
??????? }
??? }
???
??? 卸載應用程序域:
??? class AppDomain2
??? {
??????? public static void Main()
??????? {
???????????? Console.WriteLine("Creating new AppDomain.");
???????????? //創建應用程序域
???????????? AppDomain domain = AppDomain.CreateDomain("MyDomain", null);
???????????? Console.WriteLine("Host domain: " + AppDomain.CurrentDomain.FriendlyName);
???????????? Console.WriteLine("child domain: " + domain.FriendlyName);
???????????? // 卸載應用程序域
???????????? AppDomain.Unload(domain);
???????????? Console.WriteLine("Host domain: " + AppDomain.CurrentDomain.FriendlyName);
???????????? //下面這行代碼會產生異常,因為domain對象被卸載了
???????????? Console.WriteLine("child domain: " + domain.FriendlyName);
???????? }
??? }
??? 將程序集加載到應用程序域中
??? class AppDomain3
??? {
??????? public static void Main(string[] args)
??????? {
??????????? //取得當前應用程序域
??????????? AppDomain ad = AppDomain.CurrentDomain;
??????????? //加載ClassLibrary831應用程序集
??????????? Assembly a = ad.Load("ClassLibrary831");
??????????? //取得應用程序集中的NewClass類型
??????????? Type t = a.GetType("ClassLibrary831.NewClass");
??????????? //創建NewClass類型的實例
??????????? object o = Activator.CreateInstance(t);
??????????? //給對象的屬性賦值
??????????? PropertyInfo p1 = t.GetProperty("MyName");
??????????? PropertyInfo p2 = t.GetProperty("MyInfo");
??????????? p1.SetValue(o, "中國", null);
??????????? p2.SetValue(o,"China",null);
??????????? //調用對象的show方法
??????????? MethodInfo mi = t.GetMethod("show");
??????????? mi.Invoke(o, null);
??????? }
??? }
???
??? 創建一個新的應用程序域,并加載執行程序集
??? class Test
??? {
??????? static void Main(string[] args)
??????? {
??????????? AppDomain currentDomain = AppDomain.CurrentDomain;
??????????? Console.WriteLine(currentDomain.FriendlyName);
??????????? //創建新的應用程序域
??????????? AppDomain secondDomain = AppDomain.CreateDomain("New AppDomain");
??????????? //在新的應用程序域中加載執行AssemblyA.exe程序集
??????????? secondDomain.ExecuteAssembly("AssemblyA.exe");
??????? }
?? }
轉載于:https://www.cnblogs.com/30ErLi/archive/2010/09/17/1828970.html
總結
- 上一篇: ref和out的区别
- 下一篇: 为何电视剧的每一集,其执导者都不一样