昨天写了文章《关于Remoting》,感觉有些问题没有说清楚。后来又看了一些文档和书,整理了一下,就算是续吧。

其实我发现主要的问题还是集中在客户端激活模式。我想再谈谈客户端激活模式和服务器端激活模式两者在代码实现上的区别。这两种模式在服务器监听程序上的区别不大,前面那篇文章已经说得很清楚了,主要还是客户端程序。为了让概念不至于模糊混淆,我下面提到客户端激活模式,用Activated;服务器激活模式,用WellKnown。

先从VS提供的方法来看:

WellKnown模式:Activator.GetObject()方法。它的返回值是方法参数里指定类型的对象实例。

ServerRemoteObject.IServerObject serverObj = (ServerRemoteObject.IServerObject)
                Activator.GetObject(
                typeof(ServerRemoteObject.IServerObject),
                "tcp://localhost:8080/ServiceMessage");

Activated模式:
有两种方法:
1、静态方法:RemotingConfiguration.RegisterActivatedClientType()。这个方法返回值为Void,它只是将远程对象注册在客户端而已。具体的实例化还需要调用对象类的构造函数。

 RemotingConfiguration.RegisterActivatedClientType(                
                typeof(ServerRemoteObject.ServerObject),
                "tcp://localhost:8080/ServiceMessage");
            ServerRemoteObject.ServerObject serverObj = new ServerRemoteObject.ServerObject();

2、Activator.CreateInstance()方法。这个方法将创建方法参数指定类型的类对象。它与前面的GetObject()不同的是,它要在客户端调用构造函数,而GetObject()只是获得对象,而创建实例是在服务器端完成的。CreateInstance()方法有很多个重载,我着重说一下其中常用的两个。
1) public static object CreateInstance(Type type, object[] args, object[] activationAttributes);
参数说明:
type:要创建的对象的类型。
args :与要调用构造函数的参数数量、顺序和类型匹配的参数数组。如果 args 为空数组或空引用(Visual Basic 中为 Nothing),则调用不带任何参数的构造函数(默认构造函数)。
activationAttributes :包含一个或多个可以参与激活的属性的数组。

这里的参数args是一个object[]数组类型。它可以传递要创建对象的构造函数中的参数。从这里其实可以得到一个结论:WellKnown激活模式所传递的远程对象类,只能使用默认的构造函数;而Activated模式则可以用户自定义构造函数。

activationAttributes参数在这个方法中通常用来传递服务器的url。
假设我们的远程对象类ServerObject有个构造函数:

            ServerObject(string pName,string pSex,int pAge)
            {
                name = pName;
                sex = pSex;
                age = pAge;
            }

那么实现的代码是:

            object[] attrs = {new UrlAttribute("tcp://localhost:8080/ServiceMessage")};
            object[] objs = new object[3];
            objs[0] = "wayfarer";
            objs[1] = "male";
            objs[2] = 28;
            ServerRemoteObject.ServerObject = Activator.CreateInstance(
                typeof(ServerRemoteObject.ServerObject),
                objs,attrs);

可以看到,objs[]数组传递的就是构造函数的参数。

2、public static ObjectHandle CreateInstance(string assemblyName, string typeName, object[] activationAttribute);

参数说明:

assemblyName
将在其中查找名为 typeName 的类型的程序集的名称。如果 assemblyName 为空引用(Visual Basic 中为 Nothing),则搜索正在执行的程序集。
typeName
首选类型的名称。
activationAttributes
包含一个或多个可以参与激活的属性的数组。

参数说明一目了然。注意这个方法返回值为ObjectHandle类型,因此代码与前不同::

            object[] attrs = {new UrlAttribute("tcp://localhost:8080/EchoMessage")};            
            ObjectHandle handle = Activator.CreateInstance("ServerRemoteObject","ServerRemoteObject.ServerObject",attrs);
            ServerRemoteObject.ServerObject obj = (ServerRemoteObject.ServerObject)handle.Unwrap();

那么,这个方法实际上是调用的默认构造函数。ObjectHandle.Unwrap()方法是返回被包装的对象。

说明:要使用UrlAttribute,还需要在命名空间中添加:using System.Runtime.Remoting.Activation;

通过这些代码的比较,我们还可以得到一个不幸的结论:

对于Activated激活模式,不管是使用静态方法,还是使用CreateInstance()方法,都必须在客户端调用构造函数实例化对象。这样一来,在客户端我们提供的远程对象,就不可能只提供接口,而没有类的实现。而在WellKnown模式,因为在客户端只是用GetObject()获得对象,实例化是在服务器端完成的。所以客户端我们只提供接口就够了。

所以对于Activated模式,我们必须在服务器和客户端提供两份完全相同的远程对象Dll,这个结果确实让人很沮丧。有没有其他方法实现呢?鉴于它的实现原理,答案显然是否定的。我看了MSDN上的文章,唯一的可行方案就是利用前文提到的用工厂的方法。要注意的是:这种方法是一种利用WellKnown模式来模拟Activated模式,是一种方法的折中。

前文说过,服务器端远程对象,提供两个接口。一个接口是具体要传递的远程对象的接口,一个就是工厂接口。还必须有个工厂类实现工厂接口,提供创建远程对象实例的方法。

    public interface IServerObject
    {
        Person GetPersonInfo(string name,string sex,int age);
    }

    public interface IServerObjFactory
    {
        IServerObject CreateInstance();        
    }

    public class ServerObject:MarshalByRefObject,IServerObject
    {
        public Person GetPersonInfo(string name,string sex,int age)
        {
            Person person = new Person();
            person.Name = name;
            person.Sex = sex;
            person.Age = age;
            return person;
        }        
    }

    public class ServerObjFactory:MarshalByRefObject,IServerObjFactory
    {
        public IServerObject CreateInstance()
        {
            return new ServerObject();
        }
    }

而客户端呢,只提供接口就可以了。

    public interface IServerObject
    {
        Person GetPersonInfo(string name,string sex,int age);
    }

    public interface IServerObjFactory
    {
        IServerObject CreateInstance();        
    } 

然后我们用WellKnown激活模式,在服务器端:

//传递对象;
            RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(ServerRemoteObject.ServerObjFactory),
                "ServiceMessage",WellKnownObjectMode.SingleCall);

注意这里注册的不是ServerObject类对象,而是ServerObjFactory类对象。

客户端:

ServerRemoteObject.IServerObjFactory serverFactory = (ServerRemoteObject.IServerObjFactory)
                Activator.GetObject(
                typeof(ServerRemoteObject.IServerObjFactory),
                "tcp://localhost:8080/ServiceMessage");

ServerRemoteObject.IServerObject serverObj = serverFactory.CreateInstance();

首先用GetObject()返回工厂接口,再利用该接口对象调用工厂的方法CreateInstance()来创建IServerObject对象。

也许有人会纳闷了,这里使用的是WellKnown模式啊,为什么说是Activated模式呢?是这样的,本质来说,它是WellKnown模式。但由于我们利用了工厂来创建实例,因此感觉上是在客户端来创建具体的远程对象实例。因此,我说这是一种方法的折中。

好了,写到这里,自认为交待清楚了。但Remoting的实现远不止于此,还有很多高级复杂的东西我们还没有用到。例如自定义通道,自定义MarshalByReferenceObject派生类,生命周期管理,自定义代理。这些东西我也弄不清楚。如果以后弄明白了,希望能写点东西。

关于Remoting(续)相关推荐

  1. Microsoft .Net Remoting系列专题之二:Marshal、Disconnect与生命周期以及跟踪服务

    Microsoft .Net Remoting系列专题之二 一.远程对象的激活 在Remoting中有三种激活方式,一般的实现是通过RemotingServices类的静态方法来完成.工作过程事实上是 ...

  2. [转]C#中的委托和事件(续)

    源码下载:http://www.tracefact.net/SourceCode/MoreDelegate.rar C#中的委托和事件(续) 引言 如果你看过了 C#中的委托和事件 一文,我想你对委托 ...

  3. Remoting方面的转帖1

    前言:随着对Remoting的逐渐深入学习,觉得Remoting技术真是博大精深,很多内容对于我来说均是全新的知识.自知技术造诣浅陋,唯有以勤补拙.我很希望自己能写一些有用的文章,一方面记录自己的足迹 ...

  4. Microsoft .Net Remoting系列专题之二

    Microsoft .Net Remoting系列专题之二 一.远程对象的激活 在Remoting中有三种激活方式,一般的实现是通过RemotingServices类的静态方法来完成.工作过程事实上是 ...

  5. 自研GPU之火(续)

    自研GPU之火(续) 沐曦自研5nm GPU 近些年由于技术封锁,芯片产业发展受阻,自主研发的中国芯突破技术封锁一直是希望看到的. 华为也因此走上了自主研发的道路,从最基础的工艺做起,虽然速度不快,但 ...

  6. 计算机视觉一些项目实战技术(续)

    计算机视觉一些项目实战技术(续) PROTO-OBJECT BASED SALIENCY 在本项目中,提出一种新的方法来完成显著目标侦测的任务.与以往基于聚光灯注意理论的显著目标检测器相比,遵循基于对 ...

  7. 【第八篇】SAP ABAP7.5x新语法之F4增强【续】

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:SAP ABAP7.5x系列之F4增强[续] 前 ...

  8. Deep Learning 学习随记(三)续 Softmax regression练习

    上一篇讲的Softmax regression,当时时间不够,没把练习做完.这几天学车有点累,又特别想动动手自己写写matlab代码 所以等到了现在,这篇文章就当做上一篇的续吧. 回顾: 上一篇最后给 ...

  9. HDU 1429 胜利大逃亡(续) (BFS+位压缩)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)  ...

最新文章

  1. 事务的隔离级别【防止忘记自用的】
  2. 程序员级别鉴定书(.NET面试问答集锦)
  3. Android:如何实现更换主题
  4. Oracle学习:条件表达式及分组函数
  5. 施尧耘:量子计算终将实现;段路明:大规模量子计算还任重道远
  6. 手机拍照显示_最值得购买的4款5G手机,每款都有一技之长,有你在用的吗?
  7. Mockito教程:使用Mockito进行测试和模拟
  8. OpenCV中霍夫直线变换
  9. Windows平台下的Redis集群搭建(简单有效)
  10. 基于JAVA+Servlet+JSP+MYSQL的图书馆座位预约系统
  11. java学习(六)多线程 上
  12. k8s学习:部署 PHP + Redis 留言薄
  13. Android增量升级方案
  14. 国税计算机安全管理制度,武汉市国家税务局关于印发《计算机中心机房管理制度》的通知...
  15. 敏捷教练----敏捷项目管理-史诗、故事、主题
  16. linux如何初始化硬盘,Linux硬盘简易初始化(LVM)
  17. 伪概念催生人工智能行业泡沫 2018年或迎大洗牌
  18. W ndows 10模拟器,手机windows10模拟器
  19. lambda表达式无法抛出异常_Lambda 异常处理
  20. 【决策状态机FSM(finite state machine)梳理】

热门文章

  1. n卡eth挖矿设置_ETH2.0要来了,要不要布局显卡挖矿?
  2. 我在工作中是这样使用Maven
  3. 练习1.account表 添加一条记录
  4. raster | R中的栅格操作符(上)[翻译]
  5. grDevices | R语言中的配色方法汇总(Ⅱ-2)
  6. 数字化转型方法论_老板让我搞数字化转型?成功之后,我整理了这套超全的方法论...
  7. 五子棋 鼠标 C语言,c语言写的鼠标操作的五子棋游戏,欢迎观赏!
  8. python 描述符类_python的黑魔法--描述符
  9. WebPack基础入门(一):万物皆可webpack
  10. 加菲猫软件显示不能链接服务器,sql server 2012 链接服务器不能链接sql server 2000的解决方案...