.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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值