专栏首页java跬步.NET Remoting 体系结构 之 对象的激活

.NET Remoting 体系结构 之 对象的激活

客户端可以使用和创建远程 Activator 类。使用 GetObject()方法,可以得到服务器激活的远程对象或知名的远程对象的代理。CreateInstance()方法返回客户端激活的远程对象的代理。 new 运算符可以代替 Activator 类激活远程对象。为此,还必须使用 RemotingConfiguration 类在客户端中配置远程对象。

1. 应用程序的 URL

在激活对象时,必须指定远程对象的 URL。这个 URL 与使用 Web 浏览器进行浏览时所使用的 URL 相同。第一部分指定协议、服务器名或 IP 地址、端口号和 URI,其中 URI 在服务器中以下面的格式注册远程对象时指定:

protocol://server:port/URI

下面的代码示例连续使用 3 个URL 示例。在 URL 中,用 http、tcp 和ipc 指定协议,对于 HTTP 和TCP 信道,服务器名是 localhost,端口号是 8085 和8086。对于 IPC 信道,不需要定义主机名, 因为 IPC 只能在单个系统上使用。对于所有协议,URI 是Hi,如下所示:

http://localhost:8085/Hi

tcp://localhost:8086/Hi

ipc://myIPCPort/Hi

2. 激活知名对象

上面激活了知名对象。下面详细讨论一下激活顺序:

TcpClientChannel channel = new TcpClientChannel();

ChannelServices.RegisterChannel(channel);

Hello obj = (Hello)Activator.GetObject(typeof(Hello), "tcp://localhost:8086/Hi");

GetObject()是System.Activator 类的一个静态方法,它调用 Remoting Services.Connect()方法以返回远程 对象的代理对象。GetObject()方法的第一个参数指定远程对象的类型。代理实现所有公有的和受保护的方 法和属性,以便客户端可以像在真实对象上那样调用这些方法。第二个参数是远程对象的 URL。这里使用 tcp://localhost:8086/Hi 字符串,其中 tcp 定义使用的协议,localhost:8086 是主机名和端口号,后的 Hi 是 对象的 URI,其中对象在服务器上使用 method.RemotingConfiguration.RegisterWellKnownServiceType()方法指定。 也可以直接使用 RemotingServices.Connect()方法,而不使用 Activator.GetObject()方法:

Hello obj = (Hello)RemotingServices.Connect(typeof(Hello), "tcp://localhost:8086/Hi");

如果偏爱使用 new 运算符激活知名的远程对象,则可以在客户端上使用 RemotingConfiguration. RegisterWellKnownClientType()方法注册远程对象。这里需要的参数与上面相似:即远程对象的类型 和 URI。new 运算符实际上并没有创建新的远程对象,它返回一个与 Activator.GetObject()方法相似 的代理。如果使用 WellKnownObjectMode.SingleCall 标记注册远程对象,那么规则总是一样:使用 每一个方法调用创建远程对象。

RemotingConfiguration.RegisterWellKnownClientType(typeof(Hello), "tcp://localhost:8086/Hi"); Hello obj = new Hello();

3. 激活客户端激活的对象

远程对象可以保存客户端的状态。Activator.CreateInstance()方法用于创建客户端激活的远程对 象。使用 Activator.GetObject()方法,可以在调用方法时创建远程对象,而当方法执行完时,可以销 毁远程对象。对象不在服务器上保存状态,这一点与 Activator.CreateInstance()方法不同。使用静态 的 CreateInstance()方法,按次序开始激活,进而创建远程对象。在租约时间到期并且进行垃圾收集 之前,对象将一直处于激活状态。 一些重载的 Activator.CreateInstance()方法只能用于创建本地对象。为了创建远程的对象,就需 要一个能够传递激活属性的方法。下面的示例就使用其中一个重载的方法,该方法接收两个字符串 参数和一个对象数组,第一个参数是程序集的名称,第二个参数是远程对象的类型。利用第三个参 数,可以把参数传递给远程对象类的构造函数。通过 UrlAttribute 在对象数组中指定信道和对象名。 为了使用 UrlAttribute 类,必须导入 System.Runtime.Remoting.Activation 名称空间:

1 object[] attrs = {
2 new UrlAttribute("tcp://localhost:8086/HelloServer") 
3 }; 
4 ObjectHandle handle = Activator.CreateInstance( "RemoteHello", "Wrox.ProCSharp.Remoting.Hello", attrs);
5  if (handle == null) { 
6 Console.WriteLine("could not locate server"); return;
7  } 
8 Hello obj = (Hello)handle.Unwrap(); Console.WriteLine(obj.Greeting("Christian")); 

当然,对于客户端激活的对象,虽然也可以使用运算符 new 替代 Activator 类,但是使用 new 运算符,就必须使用 RemotingConfiguration.RegisterActivatedClientType()方法注册客户端激活的对 象。在客户端激活的对象体系结构中,new 运算符不但返回代理,也创建远程对象:

RemotingConfiguration.RegisterActivatedClientType(typeof(Hello), "tcp://localhost:8086/HelloServer");

Hello obj = new Hello();

4. 代理对象

Activator.GetObject()方法和 Activator.CreateInstance()方法都给客户端返回一个代理。实际上使用两个代理:即透明代理和真实代理。透明代理看起来像远程对象,它实现远程对象的所有公共方法。这些方法调用 RealProxy 的 Invoke()方法,传递包含待调用方法的消息。在消息接收器的帮助下, RealProxy 把消息发送到信道中。使用 RemotingServices.IsTransparentProxy()方法,可以检查对象是否真是透明代理。还可以通过 RemotingServices.GetRealProxy()方法获取真实代理。使用 Vasula Studio 调试器,很容易得到真实代理的所有属性:

1 ChannelServices.RegisterChannel(new TCPChannel());
2  Hello obj = (Hello)Activator.GetObject(typeof(Hello), "tcp://localhost:8086/Hi"); 
3 if (obj == null) { 
4 Console.WriteLine("could not locate server"); return; 
5 } 
6 if (RemotingServices.IsTransparentProxy(obj)) 
7 { Console.WriteLine("Using a transparent proxy"); RealProxy proxy = RemotingServices.GetRealProxy(obj); 
8 // proxy.Invoke(message); 
9 } 

5. 代理的“可插入性”

真实代理可以用自定义代理替代。自定义代理可以扩展基类 System.Runtime. Remoting.RealProxy。 在自定义代理的构造函数中接收远程对象的类型。调用 RealProxy 的构造函数,可以创建真实代理和 透明代理。在构造函数中,使用ChannelServices类创建消息接收器IChannelSender.CreateMessageSink(), 可以访问已注册信道。除了实现构造函数之外,自定义信道还必须重写 Invoke()方法。在 Invoke()方法 中,可以接收到可分析的消息,然后把它们发送到消息接收器中。

6. 消息

代理可以把消息发送到信道中。在服务器端,分析消息之后,就可以进行方法调用。因此,下 面讨论消息。 .NET Framework 有一些消息类可以用于方法调用、响应,以及返回消息等。所有消息类都可以实 现IMessage 接口,该接口只有一个 Properties 属性。Properties 属性表示一个带有 IDictionary 接口的字 典,字典中包括对象的 URI、MethodName、MethodSignature、TypeName、Args 和CallContext 等。发送给真实代理的消息是 MethodCall 类型的对象。通 过IMethodCallMessage 和 IMethodMessage 接口比通过 IMessage 接口更容易实现对消息属性的访问。 不必使用 IDictionary 接口,仍可以直接访问方法名、URI 和参数等内容。真实代理把 ReturnMessage 返回给透明代理。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C#排序算法小结

    算法这个东西其实在开发中很少用到,特别是web开发中,但是算法也很重要,因为任何的程序,任何的软件,都是由很多的算法和数据结构组成的。但是这不意味着算法对于每个...

    DougWang
  • 高性能的JavaScript--数据访问(2)

    无论是with表达式还是try-catch表达式的catch子句,以及包含()的函数,都被认为是动态作用域。一个动态作用域只因为代码运行而存在。因此无法通过静态...

    DougWang
  • js获取鼠标单击键

    利用OnMousedown和OnContextmenu添加鼠标左中右键单击的处理,返回event.button的值来判断是单击了哪个键。

    DougWang
  • 如何利用图卷积网络对图进行深度学习(上)

    基于图的机器学习是一项困难的任务,因为图的结构非常复杂,而且信息量也很大。这篇文章是关于如何用图卷积网络(GCNs)对图进行深度学习的系列文章中的第一篇,GCN...

    AiTechYun
  • 网络欺诈阻碍了三分之一的企业扩展其数字能力

    Kount发布了有关数字创新和新兴欺诈的最新研究报告,报告发现:最具创新性的业务同时也是面临最大欺诈威胁的业务。

    FB客服
  • 解决教育培训行业痛点,教育小程序必备利器来了!

    为了帮助教育培训行业解决这些痛点,微盛全新上线教育小程序音视频,基于腾讯云小程序音视频解决方案开发出专属小程序应用,给教育培训行业量身打造一站式教育解决方案。

    用户1745481
  • 图卷积网络图深度学习(上)

    基于图的机器学习是一项困难的任务,因为图的结构非常复杂,而且信息量也很大。本文是关于如何利用图卷积网络(GCNs)对图进行深度学习的系列文章中的第一篇。GCNs...

    AiTechYun
  • Github 项目推荐 | 英特尔的深度学习扩展包 —— iDeep

    iDeep 是英特尔的深度学习扩展包,用于收集加速深度学习操作(如卷积,解卷积,relu 等)的模块。iDeep 使用英特尔 MKL-DNN 作为加速引擎。

    AI研习社
  • 10分钟精通Ant Design Form表单

    antd被人吐槽最多的除了彩蛋之外,那应该就是Form表单了。如果需要使用Form自带的收集校验功能,需要使用Form.create()包装组件,每一个需要收集...

    ConardLi
  • 「黑科技」iPhone7能“飞”起来,你敢相信吗?

    镁客网

扫码关注云+社区

领取腾讯云代金券