2016-08-16 6 views
0

私はこのapiクライアントICommunicationClient(url, tenant)を私のIoCコンテナに登録しています。今、私は1からnのapiクライアントを持つことができるシナリオに直面しています。私はそれらのすべてを登録する必要があり、どのようにそれを処理するか分からない。私はSIの中にこのRegisterCollectionがあるのを見た。同じオブジェクトを異なる設定で複数回登録する

ICommunicationClientProviderを実際のクライアントのラッパーとして使用することを検討しています。それは登録されたすべてのクライアントとそれらを取得するためのメソッドを含むリストを含んでいます。私はこれが最善のアプローチではないと感じています。もちろん、私はアプリの他の部分に触れるように強制します。

public class CommunicationClientProvider : ICommunicationClientProvider 
{ 
    public CommunicationClientCollection CommunicationClientsCollection { get; set; } 
    public string Tenant { get; set; } 

    public ICommunicationClient GetClients() 
    { 
     return CommunicationClientsCollection[Tenant]; 
    } 
    public void SetClients(CommunicationClientCollection clients) 
    { 
     CommunicationClientsCollection = clients; 
    } 
} 

public interface ICommunicationClientProvider 
{ 
    ICommunicationClient GetClients(); 
    void SetClients(CommunicationClientCollection clients); 
} 

コレクション

public class CommunicationClientCollection : Dictionary<string, ICommunicationClient> 
{ 
} 

をホストするために、このここで私は、あなたがこれを行うためのより良い方法を知っていますかSI

 var clients = new CommunicationClientProvider(); 
     foreach (var supportedTenant in supportedTenants) 
     { 
      clients.CommunicationClientsCollection 
       .Add(supportedTenant, new CommunicationClient(
        new Uri(configuration.AppSettings["communication_api." + supportedTenant]), 
        new TenantClientConfiguration(supportedTenant))); 
     } 
     container.RegisterSingleton<ICommunicationClientProvider>(clients); 

に対してコレクションを登録しますか?これは、複数のデータベースがある場合などの通常のシナリオです。

UPDATE:からITenantContext部分 - これは基本的にどのように私のテナントコンテキストインターフェイスは、次のようになります。

public interface ITenantContext 
{ 
    string Tenant { get; set; } 
} 

と私は通信APIへの私のコールを作ってるんだところ、これは次のとおりです。

public class MoveRequestedHandler : IHandlerAsync<MoveRequested> 
{ 
    private readonly IJctConfigurationService _communicationClient; 
    private readonly ITenantContext _tenantContext; 

    public MoveRequestedHandler(IJctConfigurationService communicationClient, ITenantContext tenantContext) 
    { 
     _communicationClient = communicationClient; 
     _tenantContext = tenantContext; 
    } 

    public async Task<bool> Handle(MoveRequested message) 
    { 
     _tenantContext.Tenant = message.Tenant; 
     _communicationClient.ChangeApn(message.Imei, true); 

     return await Task.FromResult(true); 
    } 
} 

ここでは、ITenantContextを登録します。

container.RegisterSingleton<ITenantContext, TenantContext>(); 

テナントはMoveRequestedオブジェクト内に定義されています(message.Tenant)。 CommunicationClientにそのテナントを認識させるにはどうすればよいですか?

+0

あなたの質問は現在、あまりにも曖昧です。あなたの質問にいくつかのコードを示してください。 – Steven

+0

私は潜在的な解決策を更新しました。詳細が必要な場合はお知らせください。 – Rober

答えて

2

ICommunicationClientProviderアブストラクションを追加すると、アプリケーション全体に徹底的な変更が加えられた場合、明らかに問題があります。通常、機能を追加したり、変更を加えたりする必要はありません。実際には、あなたの現在のデザインがすでにこれを可能にしていると思います。

ICommunicationClientProvider)は工場のように機能し、factories are hardly ever the right solutionです。代わりに、Composite design patternを使用する方がはるかに優れています。たとえば、次のように

sealed class TenantCommunicationClientComposite : ICommunicationClient 
{ 
    private readonly ITenantContext tenantContext; 
    private readonly Dictionary<string, ICommunicationClient> clients; 

    public TenantCommunicationClientComposite(ITenantContext tenantContext, 
     Dictionary<string, ICommunicationClient> clients) { 
     this.tenantContext = tenantContext; 
     this.clients = clients; 
    } 

    object ICommunicationClient.ClientMethod(object parameter) => 
     this.clients[this.tenantContext.CurrentTenantName].ClientMethod(parameter); 
} 

あなたは、このクラスを登録することができます:ここではITenantContext

var dictionary = new Dictionary<string, ICommunicationClient>(); 
foreach (var supportedTenant in supportedTenants) { 
    dictionary.Add(supportedTenant, new CommunicationClient(
     new Uri(configuration.AppSettings["communication_api." + supportedTenant]), 
     new TenantClientConfiguration(supportedTenant))); 
} 

container.RegisterSingleton<ICommunicationClient>(
    new TenantCommunicationClientComposite(
     new AspNetTenantContext(), 
     dictionary)); 

あなたは現在のリクエストが実行されている代理誰に現在のテナントを取得することができます抽象化です。 AspNetTenantContextは、ASP.NETアプリケーションで現在のテナントを取得するための実装です。あなたはすでに、現在のテナントを検出するコードをすでに持っているでしょう。そのコードをAspNetTenantContextクラスに移動する必要があります。

+0

ICommunicationClientは、密集したクラスの最後のビットをどのように処理するかわからないインターフェイスの束です。 これはコンソールアプリケーションなので、ASP.Netの内容はありません。 追加:ICommunicationClientインターフェイスからすべてのメソッドを実装することになります。S – Rober

+0

@Rober:コンソールアプリケーションでは、 ITenentContext'の実装です。あなたの 'ICommunicationClient'にメンバーがたくさんいる場合、あなたは[インタフェース分離原理](https://en.wikipedia.org/wiki/Interface_segregation_principle)に違反しています。これを修正すると、醜いコンポジットの問題も解決します。 – Steven

+0

ありがとう@Stevenは、ITenantContextをどこに配置するのかまだ完全には分かっていませんが、私はそれを動作させます。私は複合物を完了しました – Rober

関連する問題