您的位置:首页 > 其它

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

2008-04-25 17:28 661 查看
看了一些WCF的例子,实现事件通知使用的是多播委托的特性,有点复杂,操作起来也不是很直观,看到一堆委托和事件我一般头就晕了。下面介绍一种使用观察者模式实现事件通知的简单方法。没别的,就是简单,简单最美。

工程代码如下:http://files.cnblogs.com/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. 这里使用的是单实例的服务,所以需要进行多进程访问的保护,才能实际使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: