2012-03-29 18 views
0

は、これは私が作るために使用される方法であるメソッドを呼び出します:変更既存のWCFの通信オブジェクト

ChannelFactory<ISomethingWebService> cnFactory = new ChannelFactory<ISomethingWebService>("SomethingWebService"); 
ISomethingWebService client = cnFactory.CreateChannel(); 

using (new OperationContextScope((IContextChannel)client)) 
{ 
    client.SomeMethod(); 
} 

私の質問は次のとおりです:

SvcHelper.Using<SomeWebServiceClient>(proxy => 
{ 
    proxy.SomeMethod(); 
} 

public class SvcHelper 
{ 
    public static void Using<TClient>(Action<TClient> action) where TClient : ICommunicationObject, IDisposable, new() 
    { 
    } 
} 

これは私がメソッド呼び出しを行う方法です代わりのすべてのインスタンスを置き換えます私の元のメソッド呼び出しのアプローチ。 SvcHelperコンストラクタ内のチャネルの作成を私SvcHelperを変更して行う方法はありますし、その後、単純に以下のようなインターフェイス渡します。これは、事前に感覚と感謝を作る

SvcHelper.Using<ISomethingWebService>(client => 
{ 
    client.SomeMethod(); 
} 

希望を。これは動作するはず

答えて

1

まず、あなたが使用してヘルパーメソッドに新しいChannelFactory<T>すべての呼び出しを作成する必要はありません。それらはWCFの宇宙で建設するのに最もコストがかかるものです。だから、最低でもそこにキャッシング・アプローチを使いたいと思うでしょう。

第2に、自分自身を「クライアント」タイプにする必要はもうありません。サービス契約のインターフェイスでまっすぐに作業してください。私は過去にこれをやった方法に基づいて行くと思いどこに持っているものから始めて

は、ここにあります:

public class SvcHelper 
{ 
    private static ConcurrentDictionary<ChannelFactoryCacheKey, ChannelFactory> ChannelFactories = new ConcurrentDictionary<ChannelFactoryCacheKey, ChannelFactory>(); 

    public static void Using<TServiceContract>(Action<TServiceContract> action) where TServiceContract : class 
    { 
     SvcHelper.Using<TServiceContract>(action, "*"); 
    } 

    public static void Using<TServiceContract>(Action<TServiceContract> action, string endpointConfigurationName) where TServiceContract : class 
    { 
     ChannelFactoryCacheKey cacheKey = new ChannelFactoryCacheKey(typeof(TServiceContract), endpointConfigurationName); 

     ChannelFactory<TServiceContract> channelFactory = (ChannelFactory<TServiceContract>)SvcHelper.ChannelFactories.GetOrAdd(
                                   cacheKey, 
                                   missingCacheKey => new ChannelFactory<TServiceContract>(missingCacheKey.EndpointConfigurationName)); 

     TServiceContract typedChannel = channelFactory.CreateChannel(); 
     IClientChannel clientChannel = (IClientChannel)typedChannel; 

     try 
     { 
      using(new OperationContextScope((IContextChannel)typedChannel)) 
      { 
       action(typedChannel); 
      } 
     } 
     finally 
     { 
      try 
      { 
       clientChannel.Close(); 
      } 
      catch 
      { 
       clientChannel.Abort(); 
      } 
     } 

    } 

    private sealed class ChannelFactoryCacheKey : IEquatable<ChannelFactoryCacheKey> 
    { 
     public ChannelFactoryCacheKey(Type channelType, string endpointConfigurationName) 
     { 
      this.channelType = channelType; 
      this.endpointConfigurationName = endpointConfigurationName; 
     } 

     private Type channelType; 

     public Type ChannelType 
     { 
      get 
      { 
       return this.channelType; 
      } 
     } 

     private string endpointConfigurationName; 

     public string EndpointConfigurationName 
     { 
      get 
      { 
       return this.endpointConfigurationName; 
      } 
     } 

     public bool Equals(ChannelFactoryCacheKey compareTo) 
     { 
      return object.ReferenceEquals(this, compareTo) 
         || 
        (compareTo != null 
         && 
        this.channelType == compareTo.channelType 
         && 
        this.endpointConfigurationName == compareTo.endpointConfigurationName); 
     } 

     public override bool Equals(object compareTo) 
     { 
      return this.Equals(compareTo as ChannelFactoryCacheKey); 
     } 

     public override int GetHashCode() 
     { 
      return this.channelType.GetHashCode()^this.endpointConfigurationName.GetHashCode(); 
     } 
    } 
} 
+0

なぜ、削除する必要があるのか​​分かりません。サンプルコードを貼り付ける前にサンプルコードをコンパイルしていました。わかりやすく接頭辞付きのメソッド呼び出しが好きなので、私は常にこれに接頭辞を付けます。またはClassName。静的呼び出しの場合 –

+0

この方法と同様にキャッシュを実装する必要がありますか? – fuzz

+1

よくChannelFactoryインスタンスのキャッシュをChannel Typeでキャッシングしていますが、実際には完全な実装になるためにType + endpointConfiguration名でキャッシュする必要があることを忘れていました。私は実装が完了するように更新します。 –

1

public class SvcHelper 
{ 
    public static void Using<TClient>(Action<TClient> action) where TClient : ICommunicationObject, IDisposable 
    { 
     ChannelFactory<TClient> cnFactory = new ChannelFactory<TClient>("SomethingWebService"); 
     TClient client = cnFactory.CreateChannel(); 
     using (new OperationContextScope((IContextChannel)client)) 
     { 
      action(client); 
     } 
    } 
} 
+0

問題は、型引数はジェネリック 'ChannelFactory'に渡されるということですクラスはインタフェース型でなければなりません。それはインターフェイスから 'ICommunicationObject'への変換がないと言います。 – fuzz

+0

「TClient:ICommunicationObject、IDisposable」を削除するのが理にかなっているかもしれません –

関連する問題