WCF中使用观察者模式实现事件通知

 1.定义接口

[ServiceContract(SessionMode  =  SessionMode.Required, CallbackContract  =   typeof (IWriteLogCallback))]
     public   interface  ILogService
    {
        [OperationContract(IsInitiating  =   true , IsTerminating  =   false )]
          void  Write( string  logMsg);

        [OperationContract(IsInitiating  =   true , IsTerminating  =   false )]
         void  RegisterListener();

        [OperationContract(IsInitiating  =   false , IsTerminating  =   false )]
         void  UnregisterListener();
    }

    [ServiceContract]
     public   interface  IWriteLogCallback
    {
        [OperationContract(IsOneWay  =   true )]
         void  OnWriteLog( string  logMsg);
    }


为了简单举了一个写日志的例子, Write(string logMsg)就是写入日志的方法,参数logMsg是需要写入的日志信息。当客户单没有调用RegisterListener()订阅事件的时候,是不会收到写日志的事件通知的,相应的要获得写日志的事件通知,就需要调用RegisterListener()方法。如果要取消订阅就调用UnregisterListener()方法。写日志的功能和事件的订阅功能是分开的。

    2.服务实现

[ServiceBehavior(
            IncludeExceptionDetailInFaults  =   true ,
            InstanceContextMode  =  InstanceContextMode.Single,
            ConcurrencyMode  =  ConcurrencyMode.Multiple)]
     class  LogService:ILogService
    {
         public  LogService()
        {
            Trace.WriteLine( " Create LogService Instance. " );
        }

        Dictionary < string , OperationContext >  listeners  =   new  Dictionary < string , OperationContext > ();

         private   void  BroadCast( string  logMsg)
        {
            List < string >  errorClints  =   new  List < string > ();

             foreach  (KeyValuePair < string , OperationContext >  listener  in  listeners)
            {
                 try
                {
                    listener.Value.GetCallbackChannel < IWriteLogCallback > ().OnWriteLog(logMsg);
                }
                 catch  (System.Exception e)
                {
                    errorClints.Add(listener.Key);
                    Trace.WriteLine( " BROAD EVENT ERROR: "   +  e.Message);
                }
            }

             foreach  ( string  id  in  errorClints)
            {
                listeners.Remove(id);
            }
        }

         #region  ILogService 成员

         public   void  Write( string  logMsg)
        {
            Trace.WriteLine( " Write LOG: " + logMsg);
            BroadCast(logMsg);
        }

         public   void  RegisterListener()
        {
            listeners.Add(OperationContext.Current.SessionId, OperationContext.Current);

            Trace.WriteLine( " SessionID: "   +  OperationContext.Current.SessionId);
            Trace.WriteLine( " Register listener. Client Count: "   +  listeners.Count.ToString());
        }

         public   void  UnregisterListener()
        {
            listeners.Remove(OperationContext.Current.SessionId);
            Trace.WriteLine( " SessionID: "   +  OperationContext.Current.SessionId);
            Trace.WriteLine( " Unregister listener. Client Count: "   +  listeners.Count.ToString());
        }

         #endregion
    }
    Dictionary<string, OperationContext> listeners包含了所有的事件订阅者。发布事件的时候,如果调用订阅者的回调函数失败,就把该订阅者从listeners移除。代码很简单,就不多说了。
    3.客户端访问
    定义回调的客户端:
class  LogClient:IWriteLogCallback
    {
         #region  IWriteLogCallback 成员

         public   void  OnWriteLog( string  logMsg)
        {
            Trace.WriteLine( " RECV LOG EVENT: "   +  logMsg);
        }

         #endregion
    }

    然后在程序中使用它:
class  Program
    {
         static   void  Main( string [] args)
        {
            Trace.Listeners.Add( new  ConsoleTraceListener());
            LogClient client  =   new  LogClient();
            ILogService service  =  DuplexChannelFactory < ILogService > .CreateChannel(client,
                 new  WSDualHttpBinding(),  new  EndpointAddress( " http://localhost:8888/log " ));
            
             // 订阅消息
            service.RegisterListener();
            service.Write( " Client start " );
            
            Console.WriteLine( " Press enter key to exit. " );
            Console.ReadLine();

            service.UnregisterListener();
        }

需要注意的问题:
A. 因为客户也要监听端口,所以确保防火墙没有对它进行阻止。
B. 这里使用的是单实例的服务,所以需要进行多进程访问的保护,才能实际使用。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值