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

添加人:iyond七级(4370分)   添加时间:2008-04-25    阅读次数:466  收藏此教程

看了一些WCF的例子,实现事件通知使用的是多播委托的特性,有点复杂,操作起来也不是很直观,看到一堆委托和事件我一般头就晕了。下面介绍一种使用观察者模式实现事件通知的简单方法。没别的,就是简单,简单最美。
工程代码如下:http://www.cnblogs.com/Files/dyj057/WcfEvent.rar
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. 这里使用的是单实例的服务,所以需要进行多进程访问的保护,才能实际使用。

来源:http://www.cnblogs.com/dyj057/archive/2008/04/25/1171352.html

1页 第1上一页1下一页
相关的教程: 工作流 Workflow WCF
收藏此教程

当前平均分: 0.0(0 次打分)

-5-4-3-2-1012345
评论主题
您的大名
您的评论
验证码 点击换一个验证码
知识库搜索: