WCF 项目应用连载[9] - 契约中的委托 & 事件参数处理
来源:互联网 发布:xp不能访问网络位置 编辑:程序博客网 时间:2024/06/05 07:07
这节是一节辅助内容。。将说清楚Lig日志系统中是怎样使用事件参数与委托参数的。
1) WCF服务接口中不能直接使用委托参数。
2) WCF采用回调接口来实现双向通信,我们可以将WCF回调接口消息封装为事件消息,在客户端接口订阅该事件消息,从而将Server消息发送给Client。
(WCF服务接口在Server端实现,WCF服务接口声明的回调接口在客户端实现)
8.1 WCF服务接口与回调接口
___________________________________________________________________________________________________________
[ServiceContract(CallbackContract = typeof(ILigAgentCallback))] public interface ILigAgent { [OperationContract] LigStatus RegisterClient(string name); [OperationContract] LigStatus UnregisterClient(int clientID); [OperationContract] LigStatus Subscribe(int clientID); [OperationContract] LigStatus Unsubscribe(int clientID); [OperationContract] void LigMessage(string message, LigLevel level); [OperationContract] void LigInfo(string message); [OperationContract] void LigDebug(string message); [OperationContract] void LigWarn(string message); [OperationContract] void LigError(string message); [OperationContract(Name = "LigFatal")] void LigFatal(string message); [OperationContract(Name = "LigFatalex")] void LigFatal(string message, Exception ex); [OperationContract] void SayHelloToServer(string message); [OperationContract] void Initialize(string ligPath); } public interface ILigAgentCallback { [OperationContract(IsOneWay = true)] void OnNotifyMessage(string message); [OperationContract(IsOneWay = true)] void OnNotifyOnline(LigArgs args); }
关键点:客户端ILigger接口出现委托参数
public interface ILigger { bool ConnectStatus { get; } int ClientID { get; } bool SubscribeOnlineEvent(EventHandler onlined); bool UnsubscribeOnlineEvent(int clientID); void LigMessage(string message, int level); void LigInfo(string message); void LigDebug(string message); void LigWarn(string message); void LigError(string message); void LigFatal(string message); }
我们在ILigger中看到了含委托参数的接口:
bool SubscribeOnlineEvent(EventHandleronlined);
为什么我们不直接在ILigAgent中加入这样的接口?下这种做法理论是是可行的,也不会导致程序编译错误。如果客户端调用下面的含委托参数的接口,会导致WCF客户端运行调用错误。。客户端调用会报一个通道状态为Fault的异常。。
那我们如来来用呢?
[OperationContract]
bool SubscribeOnlineEvent(EventHandleronlined);
8.1.1 WCF回调接口
___________________________________________________________________________________________________________
WCF的双向通信通过回调接口实现。每一个WCF服务接口都可以显式的声明一个回调接口
回调接口由客户端实现,这样我们可以在Server端通过
public sealed class OperationContext : IExtensibleObject<OperationContext>
中的成员获取客户端回调实例,然后用这该实例(T) 调用回调接口中的方法成员,从而将消息从服务端发送给指定客户端。。
public T GetCallbackChannel<T>();
___________________________________________________________________________________________________________
private event EventHandler onlineEvent; private event EventHandler MessageRecv;
1) 回到LiggerBase类,我们Ligger使用的基类。的LiggerBase内部有两个事件参数:onlineEvent与MessageRecv。
2)在LiggerBase的内部我们定义了一个LigAgentCallback 实现了WCF的回调接口ILigAgentCallback,并在LiggerBase内部订阅了msgReceived事件与onlined事件
这样,WCF回调接口中的消息发送送到了LiggerBase内部的OnNotifyMessage与OnNotifyOnline。
【LiggerBase内部订阅LigAgentCallback的msgReceived事件与onlined事件】
private void SubscribedEvents() { this.callbackInstance.msgReceived += new MessageHandler(OnNotifyMessage); this.callbackInstance.onlined += new OnlineHandler(OnNotifyOnline); }
【WCF中LigAgentCallback 回调消息类】
#region InnerClasses class LigAgentCallback : ILigAgentCallback { internal LigAgentCallback() { } internal event MessageHandler msgReceived; internal event OnlineHandler onlined; public void OnNotifyMessage(string message) { if (this.msgReceived != null) { this.msgReceived(message); } } public void OnNotifyOnline(LigArgs args) { if (this.onlined != null) { this.onlined(args); } } internal void Release() { if (this.msgReceived != null) { Delegate[] items = this.msgReceived.GetInvocationList(); foreach (Delegate item in items) { this.msgReceived -= (MessageHandler)item; } } if (this.onlined != null) { Delegate[] items = this.onlined.GetInvocationList(); foreach (Delegate item in items) { this.onlined -= (OnlineHandler)item; } } } } #endregion
【ILigger接口订阅内部事件onlineEvent事件消息】
public bool SubscribeOnlineEvent(EventHandler onlined) { bool isSubscribed = false; if (this.onlineEvent != null) { Delegate[] items = this.onlineEvent.GetInvocationList(); foreach (Delegate item in items) { if (onlined == (EventHandler)item) { isSubscribed = true; break; } } } if (isSubscribed) return true; this.onlineEvent += onlined; return true; }
【LiggerBase内部订阅的WCF回调接口消息 , 此处LiggerBase将WCF回调接口中的消息传递给了客户端订阅onlineEvent事件绑定的方法列表。。。】
private void OnNotifyOnline(LigArgs args) { LiggerEventArgs eventArgs = new LiggerEventArgs(); eventArgs.ClientID = args.ClientID; eventArgs.ConnectStatus = args.ConnectStatus; eventArgs.Message = args.Message; this.clientID = args.ClientID; this.connectStatus = args.ConnectStatus; if (this.onlineEvent != null) { this.onlineEvent(this,eventArgs); } }
8.2 WCF服务接口事件封装解决之道
___________________________________________________________________________________________________________
1)默认条件下,WCF采用XML方式序列化,DataContractSerializer是WCF的默认序列化器,该类从XmlObjectSerializer类继承。Client与Server之间以XML Message方式进行信息交互。。
___________________________________________________________________________________________________________
2) 同时含委托与事件参数的类需要继承MarshalByRefObject
___________________________________________________________________________________________________________
关于这个问题的最终答案,我也追寻了很久。。。。
实际上这不是本质的原因,本质原因是WCF默认序列化方式为XML方式,而非事件与委托要求的SOAP。。不使用委托不是解决之道。这儿我们其实需要的是一种解决方法,而不是一段话。。。。
8.6 最后
___________________________________________________________________________________________________________
___________________________________
这儿。。。Ligger实际上只发生了对LiggBase的近接调用,注意此处我们没用Ligger继承LiggerBase,是因为Ligger不想暴露LiggerBase对WCF服务接口封装资源。。。这样让Client-Server间的耦合降低。。。。。。
- WCF 项目应用连载[9] - 契约中的委托 & 事件参数处理
- WCF 项目应用连载[11] - 结束
- WCF 项目应用连载[2] - 创建Lig日志系统
- WCF 项目应用连载[4] - 自定义配置 扩展ServiceHost - LServiceHost
- WCF 项目应用连载[10] - 安全 X_509证书
- WCF中的四种契约模式
- WCF 契约
- .Net中的委托以及事件处理
- .Net中的委托以及事件处理
- 代表delegate应用之1----.Net中的委托以及事件处理
- JS中的事件委托和移除事件处理程序
- Net中的委托以及事件处理,是现实中的例子
- C#中的委托与事件在Unity中的应用
- WCF 项目应用连载[1] - 索引 - 轻量级的Log系统 - Lig Sample -序
- WCF 项目应用连载[3] - 双向通信 实例管理与服务端监控
- WCF 项目应用连载[5] - 自定义配置 扩展ChannelFactory<T> - LDuplex<T>
- WCF 项目应用连载[6] - 升级Lig服务 - 设计ILigger 构建一个完善的Lig版本
- WCF 项目应用连载[7] - 绑定、服务、行为 大数据传输与限流 - 上
- 理解python "with"关键字
- KVM虚拟机源代码分析
- 框架设计之ADO.NET Command的ExecuteScalar误用情景及底层解说
- 查找csdn排名靠前的博客
- SAP SMARTFORMS字段处理的几个小技巧
- WCF 项目应用连载[9] - 契约中的委托 & 事件参数处理
- LINQ之路 3:C# 3.0的语言功能(下)
- 线性代数:零空间
- ICE第三篇------一些疑难点
- Java EE开发四大常用框架
- HDU1863 畅通工程
- java第九章
- springMVC + swfupload 附件上传功能的实现
- 计算机应用与社会化分析 (一)