AppDomain 应用程序域 ( 实现程序集动态卸载或加载 )

时间:2022-12-03 03:13:43

AppDomain

意义:

应用程序域,应用程序执行边界,一个应用程序运行的进程中可以有多个应用程序域

C#通过 AppDomain 应用程序域实现程序集动态卸载或加载

语法1:

构造应用程序域启动项

AppDomainSetup 应用程序域启动对象名ads = new AppDomainSetup();

ads.ApplicationBase = System.Environment.CurrentDirectory;  //  设置目录
ads.DisallowBindingRedirects = false;  //  是否允许重定向
ads.DisallowCodeDownload = true;  //  是否允许http下载
ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;  //  获取配置文件

语法2:

创建应用程序域

AppDomain 新的应用程序域实例名ad2= AppDomain.CreateDomain("应用程序域显示名称", null, 应用程序域启动对象);

语法3:

加载类型

类型MarshalByRefType 对象名mbrt= (类型MarshalByRefType)应用程序域启动对象名.CreateInstanceAndUnwrap( exeAssembly, typeof(类型MarshalByRefType).FullName  );

语法4:

方法调用

对象名mbrt.方法SomeMethod(方法参数值);

语法5:

卸载当前进程中的应用程序域

AppDomain.Unload(新的应用程序域实例名ad2);

 示例:

using System;
using System.Reflection;
using System.Threading;

class Module1
{
    //C#通过 AppDomain 应用程序域实现程序集动态卸载或加载
    //应用程序域,应用程序执行边界,一个应用程序运行的进程中可以有多个应用程序域
  
    public static void Main()
    {
        // 获得当前应用程序的运行在进程中的名称.
        string callingDomainName = Thread.GetDomain().FriendlyName;
        Console.WriteLine(callingDomainName);

        // 获取程序集的显示名
        string exeAssembly = Assembly.GetEntryAssembly().FullName;
        Console.WriteLine(exeAssembly);

        // 构造应用程序域启动项
        AppDomainSetup ads = new AppDomainSetup();
        ads.ApplicationBase = System.Environment.CurrentDirectory;
        ads.DisallowBindingRedirects = false;
        ads.DisallowCodeDownload = true;
        ads.ConfigurationFile =  AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;

        // 创建应用程序域
        AppDomain ad2 = AppDomain.CreateDomain("AD #2", null, ads);

        // 加载类型
        MarshalByRefType mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap( exeAssembly, typeof(MarshalByRefType).FullName  );

        // 调用类型方法
        mbrt.SomeMethod(callingDomainName);

        // 卸载当前进程中的应用程序域
        AppDomain.Unload(ad2);
        try
        {
            // 再次调用类型方法,自动抛出异常,该类型已不存在该进程中
            mbrt.SomeMethod(callingDomainName);
            Console.WriteLine("Sucessful call.");
        }
        catch (AppDomainUnloadedException)
        {
            Console.WriteLine("Failed call; this is expected.");
        }
        Console.ReadLine();
    }
}

//代理类
public class MarshalByRefType : MarshalByRefObject
{
    //  自定义方法。
    public void SomeMethod(string callingDomainName)
    {
        // 获取此实例的应用程序域配置信息
        AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation;
        Console.WriteLine("AppName={0}, AppBase={1}, ConfigFile={2}",
            ads.ApplicationName,
            ads.ApplicationBase,
            ads.ConfigurationFile
        );

        // 显示调用AppDomain的名字,第二个域。注:应用程序的线程转换之间应用程序域。
        Console.WriteLine("Calling from '{0}' to '{1}'.",
            callingDomainName,
            Thread.GetDomain().FriendlyName
        );
    }
}

/* 控制台输出结果:

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.
 */