使用.Net建立的可执行程序*.exe,并没有直接承载到进程当中,而是承载到应用程序域(AppDomain)当中。应用程序域是.Net引入的一个新概念,它比进程所占用的资源要少,可以被看做是一个轻量级的进程。一个应用程序域可以有多个线程,一个线程也可以穿梭于多个应用程序域。

  在一个进程中可以包含多个应用程序域,一个应用程序域可以装在一个可执行程序(*.exe)或者多个程序集(*.dll)。这样可以使应用程序域之间实现深度隔离,即使进程中的某个应用程序域出现错误,也不会影响其他应用程序域的正常运作。

  当一个程序集同时被多个应用程序域调用时,会出现两种情况:

  1. CLR分别为不同的应用程序域加载此程序集。
  2. CLR把此程序集加载到所有的应用程序域之外,并实现程序集共享,此情况比较特殊,被称作为Domain Neutarl。

  应用程序域:(Application Domain,简称App Domain)一组程序集的一个逻辑容器,进程中的一个逻辑分区。通常由运行时宿主创建和操作。AppDomain唯一的作用就是进行隔离。

  具体功能:

  1. 隔离,一个AppDomain中的代码创建的对象不能由另一个AppDomain中的代码直接访问。达到隔离应用程序的效果。当然如果要访问别的AppDomain中的内容,可以使用“按引用封送”或者“按值封送”的语义。
  2. AppDomain可以卸载,但不能卸载单独的程序集或类型,只能卸载整个应用程序域。从而卸载包含在该AppDomain中的所有程序集。
  3. AppDomain可以单独保护,AppDomain在创建后,会应用一个权限集,它决定了向这个AppDomain中运行的程序集授予的最大权限。从而保护宿主加载的代码不被破坏。
  4. 可以单独实施配置,AppDomain在创建后,会关联一组配置设置。这些设置主要影响CLR在AppDomain中加载程序集的方式。这些设置涉及搜索路径、版本重定向、卷影复制以及加载器优化。
  适合使用AppDomain的条件:
  1. 需要隔离的程序集,譬如一些特别容易引起崩溃的代码可以考虑单独运行于一个特定的 appDomain;
  2. 不同安全级别的程序集,如果需要为自己的代码划分安全执行的边界,可以考虑将不同安全级别的代码单独创建于某个设定了不同安全信息的 appDomain
  3. 从性能上考虑,有些程序集可能会消耗大量资源,尽管在托管环境下,基本上不存在资源消耗漏洞,但是总会存在特定时间访问密集造成消耗大量资源的情况,这时可以考虑创建单独的 appDomain ,在资源消耗超过临界点后进行 appDomain 的卸载,适应系统运行要求。 Asp.net 中利用不同的appDomain 来提供支持就是为了防止一个应用程序的崩溃影响其他 asp.net 应用程序,同时 , 在不重新启动的系统不重新启动 IIS 不影响 asp.net 自身服务提供的情况下将一个 appDomain 卸掉同时启动新的 appDomain ,理想情况下可以实现 web 系统的长时间在线(这以往是昂贵的 unix 的特性,终于被 MS “借鉴”了)。
  4. 不同版本的同一应用程序集的同时运行。这个在 COM 时代是一个大问题,现在通过 appDomain ,实现了在一个进程中执行版本不同的两个程序集,可以做到良好的兼容性。
  5. 动态加载一些程序。

一、AppDomain的属性与方法

  在System命名空间下就存在AppDomain类,用于管理应用程序域。

  AppDomain的常用属性:

属性 说明
ActivationContext 获取当前应用程序域的激活上下文。
ApplicationIdentity 获得应用程序域中的应用程序标识。
BaseDirectory 获取基目录。
CurrentDomain 获取当前 Thread 的当前应用程序域。
Id 获得一个整数,该整数唯一标识进程中的应用程序域。
RelativeSearchPath 获取相对于基目录的路径,在此程序集冲突解决程序应探测专用程序集。
SetupInformation 获取此实例的应用程序域配置信息。

  AppDomain的常用方法:

方法 说明
CreateDomain 创建新的应用程序域。
CreateInstance 创建在指定程序集中定义的指定类型的新实例。
CreateInstanceFrom 创建在指定程序集文件中定义的指定类型的新实例。
DoCallBack 在另一个应用程序域中执行代码,该应用程序域由指定的委托标识。
ExecuteAssembly 执行指定文件中包含的程序集。
ExecuteAssemblyByName 执行程序集。
GetAssemblies 获取已加载到此应用程序域的执行上下文中的程序集。
GetCurrentThreadId 获取当前线程标识符。
GetData 为指定名称获取存储在当前应用程序域中的值。
IsDefaultAppDomain 返回一个值,指示应用程序域是否是进程的默认应用程序域。
SetData 为应用程序域属性分配值。
Load 将 Assembly 加载到此应用程序域中。
Unload 卸载指定的应用程序域。

  AppDomain事件:

事件 说明
AssemblyLoad 在加载程序集时发生。
AssemblyResolve 在对程序集的解析失败时发生。
DomainUnload 在即将卸载 AppDomain 时发生。
ProcessExit 当默认应用程序域的父进程存在时发生。
ReflectionOnlyAssemblyResolve 当程序集的解析在只反射上下文中失败时发生。
ResourceResolve 当资源解析因资源不是程序集中的有效链接资源或嵌入资源而失败时发生。
TypeResolve 在对类型的解析失败时发生。
UnhandledException 当某个异常未被捕获时出现。

二、在AppDomain中加载程序集

  通过CreateDomain方法可以建立一个新的应用程序域。

  下面给出一个使用CreateDomain建立一个应用程序域,并使用Load方法加载程序集Model.dll。

  最后使用GetAssemblies方法,列举此应用程序域中的所有程序集。

    public class Program
{
static void Main(string[] args)
{
var domain = AppDomain.CreateDomain("MyAppDomain");
domain.Load(@"控制台 - 学习测试");
foreach (var assembly in domain.GetAssemblies())
{
Console.WriteLine(assembly.FullName);
} Console.ReadKey();
}
}

  输出结果如下:

  

  注意:当加载程序集后,就无法把它从AppDomain中卸载,只能把整个AppDomain卸载。

  当需要在AppDomain加载可执行程序时,可以使用ExecuteAssembly方法。

  如,建一个控制台程序:

    class Program
{
static void Main(string[] args)
{
Console.WriteLine("供应用程序域执行!");
Console.ReadKey();
}
}

  将上面程序生成的路径保存到:C:\Users\ChenZhuo\Desktop\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe

  下面我们创建一个应用程序域并执行上面那个程序集:

    public class Program
{
static void Main(string[] args)
{
var domain = AppDomain.CreateDomain("MyAppDomain");
       //执行指定的程序集
domain.ExecuteAssembly(@"C:\Users\ChenZhuo\Desktop\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe");
Console.ReadKey();
}
}

  输出结果如下:

  

三、卸载应用程序域

  通过Unload可以卸载AppDomain,在AppDomain卸载时将会触发DomainUnload事件。

  下面使用CreateDomain建立一个名为NewAppDomain的应用程序域。然后建立AssemblyLoad事件处理方法,在程序集加载时显示程序集的信息。最后建立DomainUnload事件处理方法,在AppDomain卸载时显示卸载信息。

    class Program
{
static void Main(string[] args)
{
//新建一个应用程序域
AppDomain MyDomain = AppDomain.CreateDomain("domain");
//建立AssemblyLoad事件处理方法
MyDomain.AssemblyLoad += (sender, e) =>
{
Console.WriteLine("程序集正在加载!" + e.LoadedAssembly.FullName);
};
//建立AssemblyUnload事件处理方法
MyDomain.DomainUnload += (sender, e) =>
{
Console.WriteLine("程序集正在卸载!");
};
//加载程序集
MyDomain.Load("MySpace");
Thread.Sleep(1000);
Console.WriteLine("正在工作中!");
//卸载程序集
AppDomain.Unload(MyDomain); Console.ReadKey();
}
}

  输出结果如下:

  

四、在AppDomain中建立程序集中指定类的对象

  使用CreateInstance方法,能建立程序集中指定类的对象。但使用此方法将返回一个ObjectHandle对象,若要将此值转换为原类型,可调用UnWrap方法。

  下面例子利用MySpace.dll程序集中的MySpace.Person对象。

namespace ConsoleApplication1
{
public class Program
{
static void Main(string[] args)
{
var person = (Person)AppDomain.CurrentDomain.CreateInstance("MySpace", "MySpace.Person").Unwrap();
person.Id = 1;
person.Name = "张飞";
Console.WriteLine(person.Id + " : " + person.Name); Console.ReadKey();
}
}
}

  Person:

namespace MySpace
{
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
}

  输出结果如下:

  

C#学习笔记----AppDomain应用程序域的更多相关文章

  1. 【WPF】学习笔记(三)——这个家伙跟电子签名板有个约定

    这篇博客依旧是以电子签名板为基础而展开的,主要是对前文([WPF]学习笔记(一)--做一个简单的电子签名板)存在的部分问题进行解释,以及部分小功能的添加.由于这篇博客是建立在学习笔记一的基础上的,所以 ...

  2. .NET Remoting学习笔记(三)信道

    目录 .NET Remoting学习笔记(一)概念 .NET Remoting学习笔记(二)激活方式 .NET Remoting学习笔记(三)信道 参考:♂风车车.Net .NET Framework ...

  3. .NET Remoting学习笔记(一)概念

    目录 .NET Remoting学习笔记(一)概念 .NET Remoting学习笔记(二)激活方式 .NET Remoting学习笔记(三)信道 背景 自接触编程以来,一直听过这个名词Remotin ...

  4. C#学习笔记——面向对象、面向组件以及类型基础

    C#学习笔记——面向对象.面向组件以及类型基础 目录 一 面向对象与面向组件 二 基元类型与 new 操作 三 值类型与引用类型 四 类型转换 五 相等性与同一性 六 对象哈希码 一 面向对象与面向组 ...

  5. Asp.Net 学习笔记(IIS不同版本和Asp.Net)

    主要目的是在网上记录一下学习笔记,如有不对,请指出 谢谢!! iis5.x: 存在问题,inet info收到动态请求后,aspnt_isapi.dll会被加载到inetinfo.exe(挂载w3sv ...

  6. 【转载】.NET Remoting学习笔记(三)信道

    目录 .NET Remoting学习笔记(一)概念 .NET Remoting学习笔记(二)激活方式 .NET Remoting学习笔记(三)信道 参考:♂风车车.Net .NET Framework ...

  7. 【转载】.NET Remoting学习笔记(一)概念

    目录 .NET Remoting学习笔记(一)概念 .NET Remoting学习笔记(二)激活方式 .NET Remoting学习笔记(三)信道 背景 自接触编程以来,一直听过这个名词Remotin ...

  8. Unity(IOC)学习笔记

    原文:Unity(IOC)学习笔记 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671/article/details/79432 ...

  9. Orleans[NET Core 3.1] 学习笔记(三)( 3 )服务端配置

    服务端配置 Silo通过SiloHostBuilder和许多补充选项类以编程方式进行配置. Silo配置有几个关键方面: Orleans集群信息 集群提供程序(不知道咋翻译) Silo到Silo和Cl ...

随机推荐

  1. maven项目部分知识

    1.maven项目在pom.xml中用add dependencies加入jar包,搜索不到jar包的解决方案: Window  --> Show View --> Other输入mave ...

  2. linux 权限操作

    添加用户 命令格式:useradd 选项 用户名 -g 缺省组(不写则默认为用户名组) -G 所属组(添加到多个用户组,逗号隔开) -c 描述信息 -d 指定家目录 useradd –g aa bb ...

  3. python——tuple元组

    >>> dir(tuple) ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', ...

  4. 11.2---字符串数组排序,删除变位词(CC150)

    这道题主义的就是,要利用数组自带的sort函数. 此外,注意,利用hash来判断是否出现了. public static ArrayList<String> sortStrings(Str ...

  5. angulaijs中的ng-upload-file与阿里云oss服务的结合,实现在浏览器端上传文件到阿里云(速度可以达到1.5M)

    2015-10-26 angularjs结合aliyun浏览器端oos文件上传加临时身份验证例子 在服务端获取sts 源码: public class StsServiceSample { // 目前 ...

  6. Python连接MySQL的准备工作

    首先要安装MySQL,64位的win7可以安装64或者32位的MySQL版本,安装之后,python需要一个工具才能连接MySQL,这个工具叫MySQL-python,去这里或者这里下载1.2.3版本 ...

  7. emmet 太 hackble 了 。。。

    http://www.open-open.com/lib/view/open1451954899292.html

  8. Java中对List集合内的元素进行顺序、倒序、随机排序的示例代码

    import java.util.Collections; import java.util.LinkedList; import java.util.List; public class Test ...

  9. Selenium 模拟人输入

    public static void type(WebElement e,String str) throws InterruptedException { String[] singleCharac ...

  10. perform

    public class ArgsTest { private List <Object> args; private ArgsTestCheckPoint checkPoint; pub ...