学习.NET中的AppDomain

什么是AppDomain?
AppDomain是一组程序集的逻辑容器,AppDomain是为了提供隔离而设计的。它提供了保护、配置和终止其中每一个应用程序的隔离

AppDomain的功能:

1.一个AppDomain中的对象不能直接访问另一个Appdomain中的对象

一个AppDomain中的代码创建对象后,则这个对象就被创建他的AppDomain所拥有,它的生存期不能超过拥有它的AppDomain,要想访问另一个AppDomain中的对象

只能使用按引用传送或按值传送的语义。这就强制建立了清晰的分隔和边界,这种隔离是AppDomain很容易从进程卸载,而不影响其他运行的AppDomain。

2.AppDomain可以被卸载

CLR不支持从AppDomain中卸载特定的程序集。但可以告诉CLR卸载一个AppDomain,从而卸载AppDomain中包含的所有程序集。

3.AppDomain可以单独保护

AppDomain创建以后会应用一个权限集,它决定了向运行在这个AppDomain中运行代码的最大权限

4.AppDomain可以配置

AppDomain创建后会关联一组配置,这些配置主要影响AppDomain加载程序集的方式。

如何跨AppDomain访问对象?

一个AppDomain要和另一个AppDomain中的类型和对象通信,只能通过良好定义的机制进行。

以下代码演示了如何创建AppDomain、在其中加载程序集并构造程序集定义的类型的实例。演示了以下三种类型在构造时的不同行为:
”按引用封送“(Marshal-By-Reference)类型,“按值封送”类型(Marshal-By-Value)以及完全不能封送的类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
class Program
{
    static void Main(string[] args)
    {
        var a = Thread.GetDomain();
        string callingDomianName = Thread.GetDomain().FriendlyName;
        AppDomain a2 = AppDomain.CreateDomain("a2");
        string exeAssembly = Assembly.GetEntryAssembly().FullName;
 
        //Demo1***使用Marshal-by-reference进行跨域通信***
        Console.WriteLine("{0}#Demo1", Environment.NewLine);
        MarshalByRefType mbrt = null;
        mbrt = (MarshalByRefType)a2.CreateInstanceAndUnwrap(exeAssembly, "ConsoleApplication1.MarshalByRefType");
        //证明得到的是一个代理对象的引用
        Console.WriteLine("是否代理={0}", RemotingServices.IsTransparentProxy(mbrt));
        //看起来像是在MarshalByRefType上调用一个方法,其实不是
        //我们是在代理类型上调用方法,代理使应用切换到真是拥有对象的AppDomian
        //并在真实的对象上调用方法
        mbrt.SomeMethod();
 
        //卸载新的AppDomain
        AppDomain.Unload(a2);
 
        try
        {
            //mbrt引用一个有效的代理对象,代理对象引用一个无效的AppDomain
            mbrt.SomeMethod();
            Console.WriteLine("成功调用");
        }
        catch (AppDomainUnloadedException)
        {
            Console.WriteLine("调用失败");
        }
 
        //***Demo2:使用Marshal-By-Value进行跨AppDomain通信
        Console.WriteLine("{0}#Demo2", Environment.NewLine);
 
        a2 = AppDomain.CreateDomain("a2");
        mbrt = (MarshalByRefType)a2.CreateInstanceAndUnwrap(exeAssembly, "ConsoleApplication1.MarshalByRefType");
        //对象方法直接返回对象副本,对象按值封送
        MarshalByValType mbvt = mbrt.MethodWithReturn();
 
        //证明得到的不是对代理对象的引用
        Console.WriteLine("是否代理={0}", RemotingServices.IsTransparentProxy(mbvt));
 
        //看起来是在MarshalByValType中调用方法,实际上也是如此
        mbvt.ToString();
   
        //卸载新的Appdomain
        AppDomain.Unload(a2);
 
        try
        {
            //我们是在对象上调用一个方法,不会抛出异常
           mbvt.ToString();
           Console.WriteLine("成功调用");
        }
        catch (AppDomainUnloadedException)
        {
            Console.WriteLine("调用失败");
        }
 
        //***Demo3:使用不可封送的类型进行跨AppDomain的通信
        Console.WriteLine("{0}#Demo3", Environment.NewLine);
        a2 = AppDomain.CreateDomain("a2");
        mbrt = (MarshalByRefType)a2.CreateInstanceAndUnwrap(exeAssembly, "ConsoleApplication1.MarshalByRefType");
        //返回一个不可封送的对象,抛出异常
        try
        {
            NonMashalbleType nmt = mbrt.MethodArgAndReturn(callingDomianName);
        }
        catch (AppDomainUnloadedException ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.ReadKey();   
    }
}
 
[Serializable]
public sealed class MarshalByRefType : MarshalByRefObject
{
    public MarshalByRefType()
    {
        Console.WriteLine("{0}的构造器在{1}中运行"this.GetType().ToString(), Thread.GetDomain().FriendlyName);
    }
 
    public void SomeMethod()
    {
        Console.WriteLine("在{0}中执行", Thread.GetDomain().FriendlyName);
    }
 
    public MarshalByValType MethodWithReturn()
    {
        Console.WriteLine("在{0}中执行", Thread.GetDomain().FriendlyName);
        MarshalByValType t = new MarshalByValType();
        return t;
    }
 
    public NonMashalbleType MethodArgAndReturn(string callingThreadName)
    {
        Console.WriteLine("来自{0}的调用", callingThreadName);
        NonMashalbleType t = new NonMashalbleType();
        return t;
    }
}
 
[Serializable]
public sealed class MarshalByValType : Object
{
    private DateTime m_time = DateTime.Now;
 
    public MarshalByValType()
    {
        Console.WriteLine("{0}的构造器在{1}中运行,创建于{2:D}"this.GetType().ToString(),
            Thread.GetDomain().FriendlyName, m_time);
    }
 
    public override string ToString()
    {
        return m_time.ToLongDateString();
    }
}
 
//不能封送的类型
public sealed class NonMashalbleType
{
    public NonMashalbleType()
    {
        Console.WriteLine("在{0}中执行", Thread.GetDomain().FriendlyName);
    }
}

  

以下是代码运行结果:

最新文章

  1. jquery EasyUI的formatter格式化函数代码
  2. MFC-01-Chapter01:Hello,MFC---1.1 Windows 编程模型
  3. sql2012还原sql2008备份文件语句
  4. 【转】SVN管理多个项目版本库
  5. js init : function ()
  6. REST_FRAMEWORK加深记忆-第二次练习官方文档2
  7. 使用next-key locks 用于搜索和索引扫描,可以防止幻读
  8. Qt多线程编程总结(二)——QMutex
  9. java基础(十五章)
  10. GCD之after
  11. 【CF487E】Tourists(圆方树)
  12. ccc切割刚体
  13. 【转】【JLINK下载失败,STLINK下载失败万能解决方案】JLINK和STLINK都无法下载时的解决办法,此时芯片并没有报废
  14. python中的各种模块(np,os,shutill)
  15. Eclipse怎么样添加智能感知提示功能(含Windows版和Mac版)
  16. JMeter初体验
  17. 用delphi实现完美屏幕截图
  18. 判断URL文件是不是在于在。
  19. Loadrunder场景设计篇——添加windows Resource计数器和指标说明
  20. 测试开发系列之Python开发mock接口(一)

热门文章

  1. Java之HSF搭建demo
  2. iOS使用UIBezierPath实现ProgressView
  3. [转] ansible批量执行命令展示
  4. 微信小程序省市区联动,自定义地区字典
  5. ES5与ES6常用语法教程之 ②解构语法糖、声明变量异同
  6. Keil version 2汉字显示乱码的解决方案
  7. Unity中的动画系统和Timeline(2) 按钮动画和2D精灵动画
  8. 安卓的一些UI美化框架的使用
  9. 【VS开发】MFC运行时库与debug、release版本之间的配置关系
  10. AKKA文档2.3(java版)—什么是角色