.NET Remoting中的事件处理
2005-08-13 20:29
316 查看
好多人都对Remoting中的事件处理很疑惑,现将完整实现Remoting中事件处理的过程写出来,并对容易犯错误的地方进行总结,希望能给大家一些帮助。
现假设有一个留言板程序:
以下代码中,MsgBoard为以Singleton模式存活于服务器端的共享留言板实例,AddMessage是客户端添加留言的接口,MsgBoard定义如下:
public class MsgBoard:MarshalByRefObject
namespace ConsoleServer
我们可以不要详细去关心服务器端程序的代码,我们只需要知道:
1,服务器注册了远程服务的类型
2,TypeFilterLevel = TypeFilterLevel.Full
由于从.NET Framework 1.1起,缺省情况下DelegateSerializationHolder不允许被反序列化,(即FormatterSink.TypeFilterLevel = TypeFilterLevel.low)。为了实现远程事件处理,我们必须解除该约束,使ServerFormatterSink.TypeFilterLevel = TypeFilterLevel.Full
我们更加需要关心的是我们的客户端代码:
namespace ConsoleClient
请注意:此处我们使用一个实例方法去订阅服务器组件的事件,该实例类型定义如下:
public class eventClass:MarshalByRefObject
{
public void msgbd_OnInfoAdded(string info)
{
Console.WriteLine("info from server event:{0}", info);
}
}
为什么要这么做?
.NET Framework要求,事件的发布者必须拥有事件订阅者的元数据,而提供元数据的简单方法,就是让服务器程序添加对客户端程序的引用,但事实上我们不需要这么做,我们将订阅者声明在远程类的程序集中,而该程序集的元数据原本就是服务器和客户端共有的。此时我们要注意到,订阅事件的类,也被申明成MarshalByRefObject,这是.NET Framework 2.0出现的一个限制,委派在序列化信息中包含了函数对应实例的地址,在服务器端回掉时,可以寻址到客户端订阅的对象实例并执行相应的成员方法,既然能被服务器寻址,则该订阅对象要求是MarshalByRefObject,这不难理解。在.NET Framework 2.0之前,我们可以使用一个包含静态函数的委派去订阅服务器组件的事件,但2.0以后,如果用一个静态成员去订阅,该响应会在服务器空间内被执行,所以我们要记住,远程处理总是处理某种形式的实例成员,而静态成员不能。
总结一下:
要实现Remoting事件远程处理,要记住以下几个原则:
1,缺省情况下DelegateSerializationHolder不允许被反序列化
2,事件发起者必须拥有订阅者的元数据
3,远程处理总是处理实例成员,且该实例必须是MarshalByReference
附加:
由于HttpChannel将ChannelSinkChain作为公开的属性所以我们能够直接修改TypeFilterLevel,而队TcpChannel,ChannelSinkChain是无法直接访问的,我们可以在监视窗口看到SinkProvider,我们只能在构造TcpChannel时去干涉它,HttpChannel和TcpChannel都可以使用配置文件的方法,但代码有助于理解。
以下是HttpChannel修改TypeFilterLevel的示例:
BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();
IDictionary props = new Hashtable();
props["port"] = 1080;
// HttpChannel chan = new HttpChannel(props, clientProv, provider);
// ChannelServices.RegisterChannel(chan);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyLibrary.MsgBoard), "MyUri", WellKnownObjectMode.Singleton);
TcpChannel myChannel = new TcpChannel(props, clientProv, serverProv);
ChannelServices.RegisterChannel(myChannel);
现假设有一个留言板程序:
以下代码中,MsgBoard为以Singleton模式存活于服务器端的共享留言板实例,AddMessage是客户端添加留言的接口,MsgBoard定义如下:
public class MsgBoard:MarshalByRefObject
namespace ConsoleServer
我们可以不要详细去关心服务器端程序的代码,我们只需要知道:
1,服务器注册了远程服务的类型
2,TypeFilterLevel = TypeFilterLevel.Full
由于从.NET Framework 1.1起,缺省情况下DelegateSerializationHolder不允许被反序列化,(即FormatterSink.TypeFilterLevel = TypeFilterLevel.low)。为了实现远程事件处理,我们必须解除该约束,使ServerFormatterSink.TypeFilterLevel = TypeFilterLevel.Full
我们更加需要关心的是我们的客户端代码:
namespace ConsoleClient
请注意:此处我们使用一个实例方法去订阅服务器组件的事件,该实例类型定义如下:
public class eventClass:MarshalByRefObject
{
public void msgbd_OnInfoAdded(string info)
{
Console.WriteLine("info from server event:{0}", info);
}
}
为什么要这么做?
.NET Framework要求,事件的发布者必须拥有事件订阅者的元数据,而提供元数据的简单方法,就是让服务器程序添加对客户端程序的引用,但事实上我们不需要这么做,我们将订阅者声明在远程类的程序集中,而该程序集的元数据原本就是服务器和客户端共有的。此时我们要注意到,订阅事件的类,也被申明成MarshalByRefObject,这是.NET Framework 2.0出现的一个限制,委派在序列化信息中包含了函数对应实例的地址,在服务器端回掉时,可以寻址到客户端订阅的对象实例并执行相应的成员方法,既然能被服务器寻址,则该订阅对象要求是MarshalByRefObject,这不难理解。在.NET Framework 2.0之前,我们可以使用一个包含静态函数的委派去订阅服务器组件的事件,但2.0以后,如果用一个静态成员去订阅,该响应会在服务器空间内被执行,所以我们要记住,远程处理总是处理某种形式的实例成员,而静态成员不能。
总结一下:
要实现Remoting事件远程处理,要记住以下几个原则:
1,缺省情况下DelegateSerializationHolder不允许被反序列化
2,事件发起者必须拥有订阅者的元数据
3,远程处理总是处理实例成员,且该实例必须是MarshalByReference
附加:
由于HttpChannel将ChannelSinkChain作为公开的属性所以我们能够直接修改TypeFilterLevel,而队TcpChannel,ChannelSinkChain是无法直接访问的,我们可以在监视窗口看到SinkProvider,我们只能在构造TcpChannel时去干涉它,HttpChannel和TcpChannel都可以使用配置文件的方法,但代码有助于理解。
以下是HttpChannel修改TypeFilterLevel的示例:
BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();
IDictionary props = new Hashtable();
props["port"] = 1080;
// HttpChannel chan = new HttpChannel(props, clientProv, provider);
// ChannelServices.RegisterChannel(chan);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyLibrary.MsgBoard), "MyUri", WellKnownObjectMode.Singleton);
TcpChannel myChannel = new TcpChannel(props, clientProv, serverProv);
ChannelServices.RegisterChannel(myChannel);
相关文章推荐
- .NET Remoting中的事件处理
- .NET Remoting中的事件处理
- .Net Remoting系列专题之三:Remoting事件处理全接触
- .NET Remoting中的事件处理(.NET Framework 2.0)
- .NET Remoting中的事件处理
- .NET Remoting中的事件处理(.NET Framework 2.0)(一)
- .NET Remoting中的事件处理
- .NET Remoting中的事件处理
- 详细解读.NET Remoting的全部事件处理
- .NET Remoting中的事件处理
- iOS事件处理机制
- Cocoa Touch事件处理流程--响应者链
- 第三十九课、Qt中的事件处理(下)------------------狄泰软件学院
- android触摸事件分发与处理简述
- NDK处理用户交互事件
- 关于Gridview激发了未处理的事件“RowDeleting”错误的处理
- Android的事件处理-android学习之旅(四十四)
- 在flash/flex程序中处理javascript的事件
- android 事件处理机制之 requestDisallowInterceptTouchEvent
- 选项卡(Tab)切换效果与关联事件处理实现