cpetco_andy

导航

代理

首先来了解下应用程序与的概念。

      应用程序域:windows操作系统运行的基本单位是进程,而进程是直接运行于非托管的环境下的,我们的.NET应用程序最终也是需要运行在进程之上。可是我们得知.NET应用程序是要运行在托管环境下的,进程的运行环境是非托管的。这时就需要一个中介者,运行于非托管的进程之上,并向我们的.NET应用程序提供托管环境,这就是AppDomain应用程序域。而且一个进程可以有若干个应用程序域。这样可以减少进程频繁切换带来的性能开销。在以前的windows程序下我们不能直接跨越进程来访问另外一个进程的对象,这属于进程的隔离级别,在.NET应用程序下,我们不能直接跨越应用程序来访问另外一个应用程序域的对象。如下代码:

// 在新AppDomain中创建一个对象
static void Test2() {
AppDomain currentDomain
= AppDomain.CurrentDomain;
Console.WriteLine(currentDomain.FriendlyName);

// 创建一个新的应用程序域 - NewDomain
AppDomain newDomain = AppDomain.CreateDomain("NewDomain");

DemoClass obj;
// 在新的应用程序域中创建对象
obj = (DemoClass)newDomain.CreateInstanceAndUnwrap("ClassLib", "ClassLib.DemoClass");
obj.ShowAppDomain();
obj.ShowCount(
"Jimmy");
obj.ShowCount(
"Jimmy");
}

       从上面的代码可以看出,DemoClass的obj对象是在当前应用程序域声明的,其引用是在当前应用程序域的。而这句代码:obj = (DemoClass)newDomain.CreateInstanceAndUnwrap("ClassLib", "ClassLib.DemoClass");是将其引用指向另外一个引用程序域的实列。运行上面的程序会出错。会出现一个异常:类型“ClassLib.DemoClass”未标记为可序列化。当把DemoClass标记为可序列化之后,上面的代码就不会出现异常。上面这些事参照张子阳老兄博客的。他的解释是这样的:标记为可序列化之后,源应用程序域会将该类的对象序列化,然后传递到目标域,将其进行反序列化,还原对象。赋值给引用。

       按照他的解释,将传递过来的对象反序列化之后,会在托管堆上给传递过来的实列分配一个地址。然后赋值给引用。但是这个对象只是一个代理而已。
       代理(Proxy): 提供了和远程对象(本例中是在NewDomain中创建的DemoClass对象)完全相同的接口(属性和方法)。.Net需要在客户端(本例中是ConsoleApp.exe)基于远程对象的元信息(metadata)创建代理。因此客户端必须包含远程对象的元信息(简单来说就是只包含名称及接口定义,但可以不包含实际的代码实现)。因为代理有着和远程对象完全一样的接口和名称,所以对于客户程序来说,代理就好像是远程对象一样;而代理实际上又并不包含向客户程序提供服务的实际代码(比如说方法体),所以代理仅仅是将自己与某一对象相绑定,然后把客户程序对自己的服务请求发送给对象。对于客户程序来说,远程对象(服务端对象)就好像是在本地;而对远程对象来说,也好像是为其本地程序提供服务。

       传值封送:上面这种通过调用CreateInstanceAndUnWrap()方法这种方式进行传值封送是一种特例。就是将整个对象传递给客户端。

       引用封送:让对象依然保留在远程(本例为NewDomain中),而在客户端仅创建代理,上面已经说了代理的接口和远程对象完全相同,所以客户端以为仍然访问的是远程对象,当客户端调用代理上的方法时,由代理将对方法的请求发送给远程对象,远程对象执行方法请求,最后再将结果传回。但是和传值封送的区别还不是很明显。难道是传值封送将方法的实现也传递过来,而引用封送传递的是方法名称和接口定义?

posted on 2011-09-28 11:13  cpetco_andy  阅读(181)  评论(1编辑  收藏  举报