2017-01-22 11 views
1

WCFのコールバックを操作する方法を理解しようとしています。WCFコールバックサービスSubscribe Unsubscribe

[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(); 
    } 
} 

そして:

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のプロジェクトを作成します。私は、次の方法により、このインタフェースを実装

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); 
} 

:私は次のインターフェイスを作成するましたWCFサービスの次の行を実行すると、EqualsメソッドのNotSupportedExceptionが発生します。

if (NorthwindCallbackService.mCallbacks.ContainsKey(callbackForClient)) 

私はこの問題の理由がIEquatableを実装していないことを理解していますが、それをサーバー側で実装する方法と、コールバックを使用する最良の方法は何ですか?

答えて

1

この回答は、質問の最後の部分についてです:

コールバックを使用するための最良の方法は何か?

byteの値を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. 
      } 
     } 
    } 
} 

:しかし、私はあなたがそうあなたがより簡単に照会することができますし、クライアントについての詳細情報を格納することができConcurrentDictionaryにコールバック先と一緒にクライアントIDを格納できるようにConcurrentDictionaryを変更することを提案しますGuidパラメータを使用してSendNotificationメソッドを拡張すると、クライアントを特定して特定のクライアントに通知を送信することもできます。

あなたも、IPアドレスまたは何でもあなたがConcurrentDictionary<Guid, ClientCallbackInfo>構文使用したい、ID、それが受信するのが好き通知の種類などのクライアントに関する詳細情報が含まれているカスタムクラスのインスタンスでConcurrentDictionary<Guid, INotifierCallback>を置き換えることができます:

public class ClientCallbackInfo 
{ 
    public INotifierCallback Callback { get; set; } 
    public string SomeOtherClientInfo { get; set; } 
} 
関連する問題