跨AppDomain通信有两种方式

  1.Marshal By reference : 传递引用

  2.Marshal By Value : 把需要传递的对象 通过序列化反序列化的方式传递过去(值拷贝)

    只有标记为 可序列化 Serializable 的类才能通过 Marshal By Value的方式通信

以下代码描述了几种跨域通信的情况

1.AppDomain是CLR的内部行为,windows完全不清楚有AppDomain的存在

2.在新的域中加载Assembly和Type最好用完整限定名(如果直接加载Type, CLR会自动加载Type所在的和所用到的Assembly)

3.默认情况下新建的应用程序域使用和当前域一样的权限设置,如果你需要手动指定权限,那么构造一个PermissionSet参数传给CreateDomain

4.同样的,如果想给应用程序设置不同的配置,构造一个AppDomainSetup传给他(可以设置配置文件,程序路径,影像拷贝什么的..)

5.跨域访问的时候不会发生线程的上下文切换

6.CreateInstanceAndUnwrap 默认调用对象的无参构造函数,当然,有些重载允许你调用有参构造函数

7.只有继承了System.MarshalByRefObject的对象才能以引用方式传递 (这是一个基类....c#又不允许多继承....还是挺麻烦的)

8.只有标记了了Serializable 的对象才能以值方式传递(内部的序列化反序列化) ,这里有比较严重的性能损耗

代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Reflection;
using System.Runtime.Remoting; namespace TestConsole
{
publicclass Program
{
staticvoid Main(string[] args)
{ // 获取一个指向应用程序域的引用
AppDomain adCallingThreadDomain = Thread.GetDomain();
// 每一个应用程序域都会被分配一个名字帮助调试 ,以下代码获取引用程序域的名字
String callingDomainName = adCallingThreadDomain.FriendlyName;
// 获取应用程序域的完整名
String exeAssembly = Assembly.GetEntryAssembly().FullName;
AppDomain ad2 =null; // ************************************************************************************************************
// 使用Marshal-by-Reference的方式跨域通信
Console.WriteLine("{0}Demo #1", Environment.NewLine);
// 建立一个域,安全和配置均使用当前域的设置
ad2 = AppDomain.CreateDomain("AD #2", null, null);
MarshalByRefType mbrt =null;
// 加载Assembly到新的域,new一个对象并且返回到当前域 (实际上返回的是一个引用代理)
mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "TestConsole.MarshalByRefType");
Console.WriteLine("Type={0}", mbrt.GetType()); // CLR 对GetType做了一些手脚,返回的是被代理数据的真实类型
// 以下代码证明我们获取的是一个代理对象
Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbrt));
// 我们调用了代理类的SomeMethod() , 代理类跨域访问真正的对象
mbrt.SomeMethod();
// 卸载新建的那个应用程序域
AppDomain.Unload(ad2);
// mbrt refers to a valid proxy object; the proxy object refers to an invalid AppDomain
try
{
// 再次调用代理类的SomeMethod() , 由于域已经被卸载 抛出一个异常
mbrt.SomeMethod();
Console.WriteLine("Successful call.");
}
catch (AppDomainUnloadedException)
{
Console.WriteLine("Failed call.");
} // ************************************************************************************************************
// 使用Marshal-by-Value 的方式跨域通信
Console.WriteLine("{0}Demo #2", Environment.NewLine);
// 新建域
ad2 = AppDomain.CreateDomain("AD #2", null, null);
// 加载程序集并创建代理类
mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "TestConsole.MarshalByRefType");
// 该方法返回了一个值的拷贝 marshaled by value (not be reference).
MarshalByValType mbvt = mbrt.MethodWithReturn();
// 证明返回值不是一个代理类
Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbvt));
// 查看返回值是谁创建的
Console.WriteLine("Returned object created "+ mbvt.ToString());
// 卸载应用程序域
AppDomain.Unload(ad2);
// 由于是值传递,那么卸载域对函数没有影响 // marshaled by value
try
{
//不会有异常抛出
Console.WriteLine("Returned object created "+ mbvt.ToString());
Console.WriteLine("Successful call.");
}
catch (AppDomainUnloadedException)
{
Console.WriteLine("Failed call.");
}
// ************************************************************************************************************
// non-marshalable type 跨域通信
Console.WriteLine("{0}Demo #3", Environment.NewLine);
ad2 = AppDomain.CreateDomain("AD #2", null, null);
mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "TestConsole.MarshalByRefType");
// 没有标记为 Serializable 的类型对象 不能通过marshaled by value 跨域通信
NonMarshalableType nmt = mbrt.MethodArgAndReturn(callingDomainName); }
} //即使没有标记为Serializable 也可以通过 marshaled-by-reference 的方式跨域通信
publicsealedclass MarshalByRefType : MarshalByRefObject
{
public MarshalByRefType()
{
Console.WriteLine("{0} ctor running in {1}",
this.GetType().ToString(), Thread.GetDomain().FriendlyName);
}
publicvoid SomeMethod()
{
Console.WriteLine("Executing in "+ Thread.GetDomain().FriendlyName);
}
public MarshalByValType MethodWithReturn()
{
Console.WriteLine("Executing in "+ Thread.GetDomain().FriendlyName);
MarshalByValType t =new MarshalByValType();
return t;
}
public NonMarshalableType MethodArgAndReturn(String callingDomainName)
{
// NOTE: callingDomainName is [Serializable]
Console.WriteLine("Calling from ‘{0}’ to ‘{1}’.",
callingDomainName, Thread.GetDomain().FriendlyName);
NonMarshalableType t =new NonMarshalableType();
return t;
}
} //只有标记为 Serializable 的类型 才能用marshaled by value 的方式跨域通信
[Serializable]
publicsealedclass MarshalByValType : Object
{
private DateTime m_creationTime = DateTime.Now; // NOTE: DateTime is [Serializable]
public MarshalByValType()
{
Console.WriteLine("{0} ctor running in {1}, Created on {2:D}",
this.GetType().ToString(),
Thread.GetDomain().FriendlyName,
m_creationTime);
}
publicoverride String ToString()
{
return m_creationTime.ToLongDateString();
}
} // 没有标记为 Serializable 的类型 不能用marshaled by value 的方式跨域通信
// [Serializable]
publicsealedclass NonMarshalableType : Object
{
public NonMarshalableType()
{
Console.WriteLine("Executing in "+ Thread.GetDomain().FriendlyName);
}
}
}

CLR via C# 读书笔记 6-2 不同AppDomain之间的通信 z的更多相关文章

  1. 10月9日Android学习笔记:活动与服务之间的通信

    最近在照着<第一行代码>这本书来学安卓,顺便记下笔记.主要的内容是Android中服务的第二种启动方式,通过活动绑定服务来启动服务,实现活动与服务之间的通信. 一. 首先创建一个服务类 p ...

  2. CLR via C# 读书笔记---常量、字段、方法和参数

    常量 常量是值从不变化的符号.定义常量符号时,它的值必须能在编译时确定.确定后,编译器将唱两只保存在程序集元数据中.使用const关键字声明常量.由于常量值从不变化,所以常量总是被视为类型定义的一部分 ...

  3. Clr Via C#读书笔记---I/O限制的异步操作

    widows如何执行I/O操作      构造调用一个FileStream对象打开一个磁盘文件-----FileStream.Read方法从文件中读取数据(此时线程从托管代码转为本地/用户模式代码)- ...

  4. Clr Via C#读书笔记---计算限制的异步操作

    线程池基础 1,线程的创建和销毁是一个昂贵的操作,线程调度以及上下文切换耗费时间和内存资源. 2,线程池是一个线程集合,供应你的用程序使用. 3,每个CLR有一个自己的线程池,线程池由CLR控制的所有 ...

  5. Clr Via C#读书笔记---CLR寄宿和应用程序域

    #1 CLR寄宿: 开发CLR时,Microsoft实际是将他实现成包含在一个dll中的COM服务器.Microsoft为CLR定义了一个标准的COM接口,并为该接口和COM服务器分配了GUID.安装 ...

  6. Clr Via C#读书笔记---程序集的加载和反射

    #1 加载程序集 Assembly.Load: public class Assembly { public static Assembly Load(AssemblyName assemblyRef ...

  7. Clr Via C#读书笔记---垃圾回收机制

    #1 垃圾回收平台的基本工作原理: 访问一个资源所需的具体步骤: 1)调用IL指令newobj,为代表资源的类型分配内存.在C#中使用new操作符,编译器就会自动生成该指令.2)初始化内存,设置资源的 ...

  8. Clr Via C#读书笔记---线程基础

    趣闻:我是一个线程:http://kb.cnblogs.com/page/542462/ 进程与线程 进程:应用程序的一个实例使用的资源的集合.每个进程都被赋予了一个虚拟地址空间. 线程:对CPU进行 ...

  9. CLR via C# 读书笔记-26.线程基础

    前言 这俩个月没怎么写文章做记录分享,一直在忙项目上线的事情,但是学习这件事情,停下来就感觉难受,clr线程这章也是反复看了好多遍,书读百遍其义自见,今天我们来聊下线程基础 1.进程是什么,以及线程起 ...

随机推荐

  1. js清空web用户控件的值

    假设你的用户控件里面有: <asp:DropDownList ID="DropDownList1" runat="server"> <asp: ...

  2. 不能将“const char [7]”转换为“LPCTSTR”

    試試用強制轉換變數型態的方法吧,像這樣(LPCTSTR)"WinSun",若不行再試L"WinSun",再不行試_L"WinSun".

  3. Centos6.5下rsync文件同步安装配置及遇到的问题解决方法

    实验节点如下: 源节点:192.168.0.111 备份节点:192.168.0.112 ------------------------------以下部分在两个节点上执行1.防火墙开放873端口( ...

  4. 本地化web开发的一个例子-jquery.i18n.properties

    关键字:Web本地化, jquery,jquery.i18n.properties. 运行环境:Chrome, IE. 本文介绍使用jquery.i18n.properties对网站前端实现本地化,支 ...

  5. WINIO64位模拟键鼠操作

    最近玩游戏有点入迷,心急升级经验,于是某天开始"挂尸体",一系列手动操作之后决定写一个外挂,模拟一系列键盘和鼠标操作,没做过游戏winform也用得少,开始以为只要简单调用winA ...

  6. [转]利用/*+Ordered*/提高查询性能

    [转]利用/*+Ordered*/提高查询性能 2009-02-06 10:46:27|  分类: Oracle |  标签: |字号大中小 订阅  消耗在准备利用Oracle执行计划机制提高查询性能 ...

  7. EF性能优化(一)

    一:背景 说到EF的性能问题,我相信都是大家比较头痛的问题,有很多初学者望而却步,可是每每菜鸟在群里面抱怨EF太慢的时候,这个时候总有一些大牛登场说一句:怪EF咯?怪你不会用! 当然我从未嫌弃过它,因 ...

  8. 安装ubuntu12.04LTS卡住以及花屏问题

    昨天在XP下用grub4dos安装了ubuntu12.04LTS,总体上还算比较顺利,中途有碰到两个异常问题,解决了记录一下. 问题一:安装过程中读取ISO镜像文件时,卡在"checking ...

  9. 问题分享:ActiveX component can't create object: "MSComDlg.CommonDialog"

    问题描述: 修改一个前辈的代码,在我自己电脑上面运行的很好,但是放到要用户电脑(win7 x64)上面却跑不了,报个如题的错误. 查了下是COMDLG32.OCX的问题,用到控件的地方是: Dim o ...

  10. java.util.List

    /* * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETA ...