标签:
使用.Net建立的可执行程序*.exe,并没有直接承载到进程当中,而是承载到应用程序域(AppDomain)当中。应用程序域是.Net引入的一个新概念,它比进程所占用的资源要少,可以被看做是一个轻量级的进程。一个应用程序域可以有多个线程,一个线程也可以穿梭于多个应用程序域。
在一个进程中可以包含多个应用程序域,一个应用程序域可以装在一个可执行程序(*.exe)或者多个程序集(*.dll)。这样可以使应用程序域之间实现深度隔离,即使进程中的某个应用程序域出现错误,也不会影响其他应用程序域的正常运作。
当一个程序集同时被多个应用程序域调用时,会出现两种情况:
应用程序域:(Application Domain,简称App Domain)一组程序集的一个逻辑容器,进程中的一个逻辑分区。通常由运行时宿主创建和操作。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 | 当某个异常未被捕获时出现。 |
通过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();
}
}
输出结果如下:

使用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; }
}
}
输出结果如下:

标签:
原文地址:http://www.cnblogs.com/changrulin/p/4775048.html