WCF中有一些方法的应用对于初学者来说还是比较容易应用。只要熟练的联系这些方法操作,一般都能牢固的掌握。看了一些WCF的例子,实现事件通知使用的是多播委托的特性,有点复杂,操作起来也不是很直观,看到一堆委托和事件我一般头就晕了。#t#
下面介绍一种使用观察者模式WCF实现事件通知的简单方法。没别的,就是简单,简单最美。
工程代码如下:
WCF实现事件通知1.定义接口
[ServiceContract(SessionModeSessionMode =
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);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
为了简单举了一个写日志的例子, Write(string logMsg)就是写入日志的方法,参数logMsg是需要写入的日志信息。当客户单没有调用RegisterListener()订阅事件的时候,是不会收到写日志的事件通知的,相应的要获得写日志的事件通知,就需要调用RegisterListener()方法。如果要取消订阅就调用UnregisterListener()方法。写日志的功能和事件的订阅功能是分开的。
WCF实现事件通知2.服务实现
[ServiceBehavior(
IncludeExceptionDetailInFaults = true,
InstanceContextModeInstanceContextMode =
InstanceContextMode.Single,
ConcurrencyModeConcurrencyMode =
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>
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
listeners包含了所有的事件订阅者。发布事件的时候,如果调用订阅者的回调函数失败,就把该订阅者从listeners移除。代码很简单,就不多说了。
WCF实现事件通知3.客户端访问
定义回调的客户端:
class LogClient:IWrite
LogCallback
{
#region IWriteLog
Callback 成员
public void OnWriteLog
(string logMsg)
{
Trace.WriteLine("RECV
LOG EVENT:" + logMsg);
}
#endregion
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
然后在程序中使用它:
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();
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
WCF实现事件通知需要注意的问题:
A. 因为客户也要监听端口,所以确保防火墙没有对它进行阻止。
B. 这里使用的是单实例的服务,所以需要进行多进程访问的保护,才能实际使用。