官方文档地址:https://docs.microsoft.com/zh-cn/dotnet/framework/app-domains

解释--表示应用程序域,它是一个应用程序在其中执行的独立环境。

用处--如果要创建将托管公共语言运行时的应用程序、要创建以编程方式卸载的工具/代码或要创建可以动态卸载和重载的可插入组件,需要创建自己的应用程序域。

(详解:https://docs.microsoft.com/zh-cn/dotnet/framework/app-domains/application-domains

补充:全局程序集缓存

安装了公共语言运行时的每台计算机均具有计算机范围的代码缓存,称为全局程序集缓存。 全局程序集缓存中存储专门指定给由计算机中若干应用程序共享的程序集。

只能在需要时才通过将程序集安装到全局程序集缓存中来共享程序集。 一般原则是:程序集依赖项保持专用,并将程序集放在应用程序目录中,除非明确要求共享该程序集。 另外,无需为了使 COM 互操作或非托管代码可以访问程序集而将程序集安装到全局程序集缓存。(亲测:程序集的安装需要安装强类型程序集,且不能在使用进程中被卸载(教程:https://docs.microsoft.com/zh-cn/dotnet/standard/assembly/sign-strong-name))

感觉AppDomain的作用是为了隔断数据,保证一个安全性。这个功能可以通过代码的健壮性来进行一个弥补。

总的来说这块的东西暂时用的不多,没有实际的经验。待有经验后补充。

补充:要想跨应用程序域通信,则需要MarshalByRefObject对象抑或是继承了他的类的对象

下面是官网DEMO

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 = AppDomain.CurrentDomain.BaseDirectory;

        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
        );
    }
}

/* This code produces output similar to the following: 

AppDomainX.exe
AppDomainX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
AppName=, AppBase=C:\AppDomain\bin, ConfigFile=C:\AppDomain\bin\AppDomainX.exe.config
Calling from 'AppDomainX.exe' to 'AD #2'.
Failed call; this is expected.
 */
using System;
using System.Reflection;

using System.Threading;
using myStringer;

class Module1
{
    public static void Main()
    {
        
        string callingDomainName = Thread.GetDomain().FriendlyName;
        Console.WriteLine(callingDomainName);

        AppDomain.CurrentDomain.SetData("xiashi","hha");

        
        string exeAssembly = Assembly.GetEntryAssembly().FullName;
        Console.WriteLine(exeAssembly);

        AppDomainSetup ads = new AppDomainSetup();
        ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;

        ads.DisallowBindingRedirects = false;
        ads.DisallowCodeDownload = true;
        ads.ConfigurationFile =
            AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;

        // Create the second AppDomain.
        AppDomain ad2 = AppDomain.CreateDomain("AD #2", null, ads);

        Assembly assembly = Assembly.LoadFile(@"C:\Users\14516\Desktop\q\myCodeLibrary.dll"); // 加载程序集(EXE 或 DLL)
        
        //dynamic obj = assembly.CreateInstance("myStringer.MarshalByRefType"); // 创建类的实例 
        //string exeAssembly1 = Assembly.GetAssembly(typeof(MarshalByRefType)).FullName;

        //// Create an instance of MarshalbyRefType in the second AppDomain. 
        //// A proxy to the object is returned.

        //MarshalByRefType mbrt = (MarshalByRefType)ad2.Load("myCodeLibrary, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").CreateInstance("myStringer.MarshalByRefType"); 
        MarshalByRefType mbrt =
            (MarshalByRefType)ad2.CreateInstanceAndUnwrap(
                "myCodeLibrary, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
                typeof(MarshalByRefType).FullName
            );
        int mbrt2 =
            ad2.ExecuteAssembly(@"E:\下载\FontAwesome.Sharp-master\ConsoleApp8\bin\Debug\ConsoleApp8.exe");


        // Call a method on the object via the proxy, passing the 
        // default AppDomain's friendly name in as a parameter.
        int i=mbrt.SomeMethod(callingDomainName);
        
        // Unload the second AppDomain. This deletes its object and 
        // invalidates the proxy object.
        AppDomain.Unload(ad2);
        Assembly[] assemblies=AppDomain.CurrentDomain.GetAssemblies();
        foreach (Assembly a in assemblies)
        {
            Console.WriteLine(a.FullName);
        }
        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.");
        }
        //Console.WriteLine(i);

        Console.ReadLine();
    }
}

// Because this class is derived from MarshalByRefObject, a proxy 
// to a MarshalByRefType object can be returned across an AppDomain 
// boundary.


/* This code produces output similar to the following: 

AppDomainX.exe
AppDomainX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
AppName=, AppBase=C:\AppDomain\bin, ConfigFile=C:\AppDomain\bin\AppDomainX.exe.config
Calling from 'AppDomainX.exe' to 'AD #2'.
Failed call; this is expected.
 */

 

posted on 2020-03-02 15:53  xiaoshibushiyue  阅读(267)  评论(0)    收藏  举报