/*** AppDomain 表示應用程序域,它是一個應用程序在其中執行的獨立環境。無法繼承此類。 應用程序域(由 AppDomain 對象表示)為執行托管代碼提供隔離、卸載和安全邊界。 使用應用程序域隔離可能終止進程的任務。如果正在執行任務的 AppDomain 的狀態變得不穩定, 則可以卸載 AppDomain,但不會影響進程。當進程必須不重新啟動而長時間運行時,這一點很重要。 還可使用應用程序域隔離不應共享數據的任務。 如果程序集被加載到默認應用程序域中,則當進程運行時將無法從內存中卸載該程序集。 但是,如果打開另一個應用程序域來加載和執行程序集,則卸載該應用程序域時也會同時卸載程序集。 使用此技術最小化長時間運行的進程的工作集,這些進程偶爾會使用大型 DLL。 多個應用程序域可以在一個進程中運行;但是,在應用程序域和線程之間沒有一對一的關聯。 多個線程可以屬於一個應用程序域,盡管給定的線程並不局限於一個應用程序域,但在任何給定時間, 線程都在一個應用程序域中執行。 應用程序域通過使用 CreateDomain 方法來創建。AppDomain 實例用於加載和執行程序集 (Assembly)。當不再使用 AppDomain 時,可以將它卸載。 AppDomain 類實現一組事件,這些事件使應用程序可以在加載程序集、要卸載應用程序域或引發未處理的異常時進行響應。 有關使用應用程序域的更多信息,請參見 應用程序域。 此類實現 MarshalByRefObject、_AppDomain 和 IEvidenceFactory 接口。 在任何情況下都不應創建 AppDomain 對象的可遠程控制的包裝。這樣做可發布對該 AppDomain 的遠程引用, 將諸如 CreateInstance 方法向遠程訪問公開,並有效損壞該 AppDomain 的代碼訪問安全性。 連接到遠程 AppDomain 的惡意客戶端可以獲得對 AppDomain 本身可訪問的所有資源的訪問權。 您不應為任何以下類型創建可遠程控制的包裝:擴展 MarshalByRefObject 的類型和實現惡意客戶端可用來繞過安全系統的方法的類型。 **/ //警告 //AppDomainSetup.DisallowCodeDownload 屬性的默認值為 false。此設置對於服務不安全。若要防止服務下載部分受信任的代碼,請將此屬性設置為 true。 //示例 //此示例顯示如何創建新的 AppDomain,在該新建 AppDomain 中實例化類型,以及與該類型的對象通信。 //此外,此示例還顯示如何卸載導致對象被垃圾回收的 AppDomain。 using System; using System.Reflection; using System.Threading; class Module1 { public static void Main() { // Get and display the friendly name of the default AppDomain. string callingDomainName = Thread.GetDomain().FriendlyName; Console.WriteLine(callingDomainName); // Get and display the full name of the EXE assembly. string exeAssembly = Assembly.GetEntryAssembly().FullName; Console.WriteLine(exeAssembly); // Construct and initialize settings for a second AppDomain. AppDomainSetup ads = new AppDomainSetup(); ads.ApplicationBase = System.Environment.CurrentDirectory; ads.DisallowBindingRedirects = false; ads.DisallowCodeDownload = true; ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; // Create the second AppDomain. AppDomain ad2 = AppDomain.CreateDomain("AD #2", null, ads); // Create an instance of MarshalbyRefType in the second AppDomain. // A proxy to the object is returned. MarshalByRefType mbrt = (MarshalByRefType) ad2.CreateInstanceAndUnwrap( exeAssembly, typeof(MarshalByRefType).FullName ); // Call a method on the object via the proxy, passing the // default AppDomain's friendly name in as a parameter. mbrt.SomeMethod(callingDomainName); // Unload the second AppDomain. This deletes its object and // invalidates the proxy object. AppDomain.Unload(ad2); try { // Call the method again. Note that this time it fails // because the second AppDomain was unloaded. mbrt.SomeMethod(callingDomainName); Console.WriteLine("Sucessful call."); } catch(AppDomainUnloadedException) { Console.WriteLine("Failed call; this is expected."); } } } // Because this class is derived from MarshalByRefObject, a proxy // to a MarshalByRefType object can be returned across an AppDomain // boundary. public class MarshalByRefType : MarshalByRefObject { // Call this method via a proxy. public void SomeMethod(string callingDomainName) { // Get this AppDomain's settings and display some of them. AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation; Console.WriteLine("AppName={0}, AppBase={1}, ConfigFile={2}", ads.ApplicationName, ads.ApplicationBase, ads.ConfigurationFile ); // Display the name of the calling AppDomain and the name // of the second domain. // NOTE: The application's thread has transitioned between // AppDomains. Console.WriteLine("Calling from '{0}' to '{1}'.", callingDomainName, Thread.GetDomain().FriendlyName ); } }