2017-10-09 10 views
0

私はIoCコンテナSimpleInjectorを使用しています。 シングルトンは目的ではないので再作成してはならないが、私の問題はWCFにあり、に入るときは何度か読んでも新しいインスタンスを作成する必要があることがわかった状態。SimpleInjector(Tridionを使用)でシングルトンインスタンスとしてWCFサービスを再作成する方法

2つのWCFサービスを使用するCoreServiceServiceというクラスがあります。

  1. CoreService
  2. ECLService

私はCoreServiceSessionへの呼び出しをたくさん作り、それらのWCFサービスを作成することがありますので、私はそれらのサービスをシングルトンにしたいが、あまりにも高価であり、多くの時間を要し作成後、はるかに高速です。

私は、このようにそれらを登録しています:

container.Register(() => new SessionAwareEclServiceClient(binding, eclServiceRemoteAddress), Lifestyle.Singleton); 

container.Register(() => new SessionAwareCoreServiceClient(binding, coreServiceRemoteAddress), Lifestyle.Singleton); 

container.Register(typeof(ICoreServiceSession), typeof(CoreServiceSession), Lifestyle.Scoped); 

私の問題は何かを取得できなかった場合ECLServiceを使用していること、私は.Abortを(呼び出す場合)にあり、近隣に、障害が発生し接続に入るということです接続。しかし、次回私がサービスを呼び出すと、ECLService WCFサービスはFaulted状態になり続けます(シングルトンなので)。そのため、接続を再作成する方法が必要です。

私は、もちろん、それは私に同じインスタンスを与え、

coreServiceSession.EclServiceClient = (SessionAwareEclServiceClient)container.GetInstance(typeof(SessionAwareEclServiceClient)); 

ようなもので試してみました。しかし。

私も

container.RegisterInitializer<ICoreServiceSession>(coreServiceSession => 
{ 
    if (coreServiceSession.EclServiceClient.State == CommunicationState.Faulted) 
    { 
     coreServiceSession.EclServiceClient.Abort(); 
     coreServiceSession.EclServiceClient = null; 
     coreServiceSession.EclServiceClient = (SessionAwareEclServiceClient)container.GetInstance(typeof(SessionAwareEclServiceClient)); 
    } 
} 

同じことを、この初期化子を使用してみました、私は、container.GetInstanceの代わりにこの使用しようとした:

coreServiceSession.EclServiceClient = new SessionAwareEclServiceClient(binding, eclServiceRemoteAddress); 

同じことを。任意のアイデア/オプション?

この場合、強制的に新しいインスタンスを取得する必要がありますか?

UPDATE

これは、事前に

public class CoreServiceSession : ICoreServiceSession 
{ 
     public CoreServiceSession(ISessionAwareCoreService sessionAwareEclServiceClient, SessionAwareCoreServiceClient sessionAwareCoreServiceClient) 
     { 
      EclServiceClient = sessionAwareEclServiceClient; 
      CoreServiceClient = sessionAwareCoreServiceClient; 
     } 

     public ISessionAwareCoreService EclServiceClient { get; set; } 

     public SessionAwareCoreServiceClient CoreServiceClient { get; set; } 

     public string CreateOrGetStubUris(string eclItemUri) 
     { 
      var stubInfo = EclServiceClient.CreateOrGetStubUris(new List<string> { eclItemUri }).FirstOrDefault(); 
     } 
} 

おかげクラスCoreServiceSessionの一部です。 Guillermo

+0

これはあなたのCoreServiceSessionは、次のようになりますどのように?クライアントコードを共有できますか? –

+0

@StinkyTowelコードの一部を追加しました – polonskyg

+0

** ISessionAwareCoreService sessionAwareEclServiceClient **の具象クライアントを作成するコードを追加できますか? –

答えて

0

@ScottHannenは、すでにチャンネルをシングルトンとして登録しないでください:作成するのは高価ではなく、チャンネル工場だけです。

実際、WCFクライアントオブジェクトをコンストラクタに挿入しないでください。それらをコンストラクタに挿入することは、それらが傍受、模擬または置換するために使用できる有用な抽象であることを意味しますが、そのようなクライアントを使用するクラスは通常、WCFに強く結合されます。

コンストラクタに注入する代わりに、コンシューマに内部でChannelFactoryを使用させてもらいます。そのようなChannelFactoryは、通常、注入する必要はありません、あなたはちょうど私的な静的フィールドでそれを新しいことができます。あなたには、いくつかの並べ替えの更新/リフレッシュを強制するために、あなたのインスタンスにメソッドを追加することができ

public class CoreServiceSession : ICoreServiceSession 
{ 
    private static readonly ChannelFactory factory = 
     new ChannelFactory<ISessionAwareCoreService>(myBinding, myEndpoint); 

    public string CreateOrGetStubUris(string eclItemUri) 
    { 
     var client = factory.CreateChannel(); 

     try 
     { 
      return EclServiceClient.CreateOrGetStubUris(
       new List<string> { eclItemUri }).FirstOrDefault(); 
     } 
     finally 
     { 
      try 
      { 
       ((IDisposable)client).Dispose(); 
      } 
      catch 
      { 
       // We need to swallow exceptions thrown by Dispose. 
       // See: https://marcgravell.blogspot.com/2008/11/dontdontuse-using.html 
      } 
     } 
    } 
} 
+1

私はこのアプローチをもう一度使い、それを何度でも成功させました。しかし、IoCの精神を守るために、私が通常行ってきたことは、IoCに登録されているFunc ()を注入し、ラムダがシングルトンChannelFactoryを使用することです。 クライアントのCleanCloseを実行する拡張メソッドも記述できます(Try-Finallyブロック内の部分 – KRam

関連する問題