学习.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);
    }
}

  

以下是代码运行结果:

学习.NET中的AppDomain的更多相关文章

  1. 学习sql中的排列组合,在园子里搜着看于是。。。

    学习sql中的排列组合,在园子里搜着看,看到篇文章,于是自己(新手)用了最最原始的sql去写出来: --需求----B, C, F, M and S住在一座房子的不同楼层.--B 不住顶层.C 不住底 ...

  2. [转]学习Nop中Routes的使用

    本文转自:http://www.cnblogs.com/miku/archive/2012/09/27/2706276.html 1. 映射路由 大型MVC项目为了扩展性,可维护性不能像一般项目在Gl ...

  3. Android学习开发中如何保持API的兼容

    Android学习开发中如何保持API的兼容: 1,采用良好的设计思路 在设计过程中,如果能按照下面的方式来进行设计,会让这个API生命更长久 面向用例的设计,收集用户建议,把自己模拟成用户,保证AP ...

  4. 学习Spring中遇到关于BeanFactory及测试类的问题

    最近在学习Spring,使用的是Spring 5.0.1 学习书本中使用的是4.0 学习书本中使用以下来加载配置文件及设置 Resource resource = new ClassPathResou ...

  5. 斯坦福大学公开课机器学习:machine learning system design | trading off precision and recall(F score公式的提出:学习算法中如何平衡(取舍)查准率和召回率的数值)

    一般来说,召回率和查准率的关系如下:1.如果需要很高的置信度的话,查准率会很高,相应的召回率很低:2.如果需要避免假阴性的话,召回率会很高,查准率会很低.下图右边显示的是召回率和查准率在一个学习算法中 ...

  6. 学习 MySQL中导入 导出CSV

    学习 MySQL中导入 导出CSV http://blog.csdn.net/sara_yhl/article/details/6850107    速度是很快的 导出 select * from t ...

  7. 如何理解并学习javascript中的面向对象(OOP) [转]

    如果你想让你的javascript代码变得更加优美,性能更加卓越.或者,你想像jQuery的作者一样,写出属于自己优秀的类库(哪怕是基于 jquery的插件).那么,你请务必要学习javascript ...

  8. Emgu-WPF学习使用-中值模糊

    原文:Emgu-WPF学习使用-中值模糊 实现效果: 实现途径: 前提:Image File-> System.Drawing.Bitmap->Image<Bgr, byte> ...

  9. Flink 从0到1学习 —— Flink 中如何管理配置?

    前言 如果你了解 Apache Flink 的话,那么你应该熟悉该如何像 Flink 发送数据或者如何从 Flink 获取数据.但是在某些情况下,我们需要将配置数据发送到 Flink 集群并从中接收一 ...

随机推荐

  1. jQuery获取元素值以及设置元素值总结

    html(): 1:用户获取元素内的HTML内容,如果元素包含子标签,会以整体的形式返回 2:只获取第一个元素的内容 3:只获取普通元素的内容,表单元素内容无法获取 html(val): 1:用来设置 ...

  2. [django]update_or_create使用场景

    update_or_create 作用是为了添加数据时防止重复. 先去查询, 如果没有在创建, 如果有则更新. update_or_create用法与密码存储实例 create方法 如果id是None ...

  3. SDK location not found. Define location with sdk.dir in the local.properties file or with an ANDROID_HOME environment variable.

    问题描述: 已经安装了android-sdk 和gradle环境,并配置了环境变量,如下所示: android环境 root@wangju-HP--G4:/home/wangju/Desktop/5i ...

  4. oracle 导入关键字说明

    关键字 说明(默认) ----------------------------------------- UserId 用户名/口令 Full     导入整个文件(N) Buffer 数据缓冲区的大 ...

  5. 小D课堂 - 新版本微服务springcloud+Docker教程_2_03常见的微服务框架

    笔记 3.常见的微服务框架     简介:讲解常用的微服务框架 consumer: 调用方         provider: 被调用方         一个接口一般都会充当两个角色(不是同时充当) ...

  6. 通过TCODE查找SPRO路径

    1.SE11:CUS_ACTOBJ,根据OBJECTNAME(对象名称),即视图名称,获取Customizing activity(ACT_ID) 2.根据ACT_ID在表CUS_IMGACT获取说明 ...

  7. URL encoding(URL编码)

    URL encoding(URL编码),也称作百分号编码(Percent-encoding),是指特定上下文的统一资源定位符(URL)编码机制UrlEncode:将字符串以URL编码返回值:字符串函数 ...

  8. vscode开发ExtJs安装插件以及破解方法

    https://blog.csdn.net/lovelyelfpop/article/details/69568995 1.官网下载vscode 插件. https://www.sencha.com/ ...

  9. appium+python等待方式使用

    背景: 首先,由于一个网速和手机性能以及服务器反应时间等等的原因,不可能导致我们点击了某一个元素之后,它所要链接的页面马上弹出来可以进行下一步操作.所以我们需要一种等待方式,直至链接的页面跳出来之后再 ...

  10. Android开发 移动端适配

    1 UI自适应(UGUI) UI自适应又分为锚点自适应和缩放.锚点主要控制UI控件在父控件之中的位置,同时也能影响缩放. 锚点自适应缩放: 我们使用UGUI创建一个界面,设计使用1920x1080分辨 ...