[英]WCF Callback service Subscribe\Unsubscribe
我試圖了解如何使用 WCF 的回調。 我正在創建下一個接口:
public interface INotifierCallback : IEquatable<INotifierCallback>
{
/// <summary>
/// Send notification.
/// </summary>
/// <param name="notification">Notification.</param>
[OperationContract(IsOneWay = true)]
void SendNotificationBack(string notification);
}
[ServiceContract(Namespace = "http://MyWCFLearning.com/NorthwindCallbackService",
CallbackContract = typeof(INotifierCallback))]
public interface INorthwindCallbackService
{
/// <summary>
/// Subscribe to notifications.
/// </summary>
[OperationContract]
void Subscribe();
/// <summary>
/// Unsubscribe from notifications.
/// </summary>
[OperationContract]
void Unsubscribe();
/// <summary>
/// Send notification.
/// </summary>
/// <param name="notification">Notification.</param>
[OperationContract(IsOneWay = true)]
void SendNotification(string notification);
}
我通過下一個方式實現這個接口:
public class NorthwindCallbackService : INorthwindCallbackService
{
/// <summary>
/// Callbacks to clients.
/// </summary>
protected static IDictionary<INotifierCallback, byte> mCallbacks { get; set; }
static NorthwindCallbackService()
{
NorthwindCallbackService.mCallbacks = new ConcurrentDictionary<INotifierCallback, byte>();
}
public void Subscribe()
{
INotifierCallback callbackForClient;
callbackForClient = OperationContext.Current.GetCallbackChannel<INotifierCallback>();
if (NorthwindCallbackService.mCallbacks.ContainsKey(callbackForClient) == false)
{
NorthwindCallbackService.mCallbacks.Add(callbackForClient, default(byte));
}
}
public void Unsubscribe()
{
INotifierCallback callbackForClient;
callbackForClient = OperationContext.Current.GetCallbackChannel<INotifierCallback>();
if (NorthwindCallbackService.mCallbacks.ContainsKey(callbackForClient))
{
NorthwindCallbackService.mCallbacks.Remove(callbackForClient);
}
}
public void SendNotification(string notification)
{
foreach (var currentCallback in NorthwindCallbackService.mCallbacks)
{
try
{
currentCallback.Key.SendNotificationBack(notification);
}
catch (ObjectDisposedException)
{
//TODO: When client of NorthwindCallbackService call Dispose() method, we should remove callback of him from NorthwindCallbackService.mCallbacks, but I do not know how to make it.
}
}
}
}
然后我創建了 UnitTest 項目,在其中添加了下一個測試方法:
[TestMethod]
public void SubscribeAndUnsubscribeTest()
{
INorthwindCallbackServiceCallback callbackHandler;
InstanceContext instanceContext;
callbackHandler = new FakeINorthwindCallbackServiceCallback();
instanceContext = new InstanceContext(callbackHandler);
using (var callbackServiceClient = new NorthwindCallbackServiceClient(instanceContext))
{
callbackServiceClient.Subscribe();
callbackServiceClient.Unsubscribe();
}
}
在執行 WCF 服務的下一行時,我有 NotSupportedException for Equals 方法:
if (NorthwindCallbackService.mCallbacks.ContainsKey(callbackForClient))
我知道這個問題的原因沒有實現 IEquatable,但是如何在服務器端實現它,以及使用回調的最佳方法是什么?
這個答案是關於問題的最后一部分:
使用回調的最佳方法是什么?
您已經了解了這個想法,但為什么不使用ConcurrentDictionary
的byte
值? 首先,沒有“最好的方法”。 但是我建議更改ConcurrentDictionary
的方式,您可以將客戶端 ID 與回調信息一起存儲到ConcurrentDictionary
以便您可以更輕松地查詢並存儲有關客戶端的更多信息:
public class NorthwindCallbackService : INorthwindCallbackService
{
/// <summary>
/// Callbacks to clients.
/// </summary>
protected static IDictionary<Guid, INotifierCallback> mCallbacks { get; set; }
static NorthwindCallbackService()
{
NorthwindCallbackService.mCallbacks = new ConcurrentDictionary<Guid, INotifierCallback>();
}
public void Subscribe(Guid clientId)
{
INotifierCallback callbackForClient;
callbackForClient = OperationContext.Current.GetCallbackChannel<INotifierCallback>();
if (NorthwindCallbackService.mCallbacks.ContainsKey(clientId) == false)
{
NorthwindCallbackService.mCallbacks.Add(clientId, callbackForClient);
}
}
public void Unsubscribe(Guid clientId)
{
INotifierCallback callbackForClient;
callbackForClient = OperationContext.Current.GetCallbackChannel<INotifierCallback>();
if (NorthwindCallbackService.mCallbacks.ContainsKey(clientId))
{
NorthwindCallbackService.mCallbacks.Remove(clientId);
}
}
public void SendNotification(string notification)
{
foreach (var currentCallback in NorthwindCallbackService.mCallbacks)
{
try
{
currentCallback.Value.SendNotificationBack(notification);
}
catch (ObjectDisposedException)
{
//TODO: When client of NorthwindCallbackService call Dispose() method, we should remove callback of him from NorthwindCallbackService.mCallbacks, but I do not know how to make it.
}
}
}
}
現在,由於您可以識別客戶端,如果您使用Guid
參數擴展SendNotification
方法,您還可以向特定客戶端發送通知。
您甚至可以將ConcurrentDictionary<Guid, INotifierCallback>
替換為自定義類的實例,該實例包含有關客戶端的更多信息,例如 Id、它喜歡接收的通知類型、IP 地址或使用ConcurrentDictionary<Guid, ClientCallbackInfo>
任何您想要的信息ConcurrentDictionary<Guid, ClientCallbackInfo>
構造:
public class ClientCallbackInfo
{
public INotifierCallback Callback { get; set; }
public string SomeOtherClientInfo { get; set; }
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.