4

Webアプリケーションが通信している別個のAPIごとにHttpClientのインスタンスを作成しています。依存性注入を使用してHttpClientの複数のインスタンスを管理する

ビジネスクラスにHttpClientを注入するには、SimpleInjectorの依存性注入を使用します。たとえば、私はITwitterBusinessIInstagramBusinessを持っていて、どちらもそのコンストラクタにHttpClientを受け入れます。

依存性注入を使用して同じタイプの複数のオブジェクトを登録する場合のベストプラクティスは何ですか?

私はこの問題の一部が私のデザインになる可能性があると確信していますが、ここにいくつかのアイデアがあります。

私の最初のアイデアは、十分に単純なようだが、この方法はSimpleInjectorが遅くなることによって、例えば、任意の悪い副作用を持っている場合、私は知りませんDI登録

container.Register<ITwitterBusiness>(() => new TwitterBusiness(httpClientTwitter)); 

にデリゲートを使用することですまたは私はいくつかのデザインパターンを壊している場合。

私の第二の考えは、私はこれは私が特定のクラスに特定のHttpClientインスタンスを注入することを可能にすると信じてコンテキストベースの注入http://simpleinjector.readthedocs.io/en/latest/advanced.html#context-based-injection

を使用することです。それがどのように機能するかはまだ正確には分かりません。

これを純粋に設計で解決できるかどうかは非常に不思議です。たとえば、ダミークラスを作成します。私はちょうど良い例は見つけられませんでしたが、正しく理解すれば、HttpClientTwitterのようなダミークラスを作成してHttpClientを継承し、あいまいな登録を取り除くことができます。

ありがとうございます!

答えて

3

私の最初のアイデアは、DI登録でデリゲートを使用することです。シンプルだが、SimpleInjectorの実行を遅くするなど、この方法に悪影響があるかどうか、あるいは私がいくつかのデザインパターンを壊しているかどうかはわかりません。

タイプに配線が必要なアプリケーションコンポーネントがある場合は、自動配線(デリゲートの登録とは逆の方法)を使用することをお勧めします。自動配線は登録を簡単にし、Simple Injectorがオブジェクトグラフを分析できるようにします。あなたの場合はどちらも心配していないようです。 HttpClientはアプリケーションコンポーネントではなく、インフラストラクチャタイプです。他の依存関係はないようですので、デリゲートを登録しても保守性の問題は発生しません。

自動配線の使用に比べて、代理人の登録が遅くなるため、シンプルインジェクタは代理人を使用して最適化することができません。しかし、非常に、非常にこれを行う際にパフォーマンスの違いに気付くことはほとんどありません。これはあなたが心配するべきではありません。

私の2番目のアイデアは、コンテキストベースの注入を使用することです。私はこれが特定のクラスに特定のHttpClientインスタンスを注入することができると信じています。それがどのように機能するかはまだ正確には分かりません。

コンテキストに基づいて異なる登録を行うことができます。例えば:私はあなたが柔軟性の誤った感覚を得るTwitterBusinessクラスにHttpClientを注入することにより、設計

によって純粋にこの問題を解決することができれば

var httpClientTwitterRegistration = Lifestyle.Transient.CreateRegistration<HttpClient>(
    () => new HttpClient("https://twitter"), 
    container); 

container.RegisterConditional(typeof(HttpClient), httpClientTwitterRegistration, 
    c => c.Consumer.ImplementationType == typeof(TwitterBusiness)); 

var httpClientInstagramRegistration = Lifestyle.Transient.CreateRegistration<HttpClient>(
    () => new HttpClient("https://instagram"), 
    container); 

container.RegisterConditional(typeof(HttpClient), httpClientInstagramRegistration, 
    c => c.Consumer.ImplementationType == typeof(InstagramBusiness)); 

私は非常に興味があります。あなたは2つのスワップ実装が可能であるようですが、HttpClientは具体的な型であるため、実装の変更は理にかなっていません。 TwitterBusinessHttpClientと直接通信するため、これは実装の詳細にする必要があります。つまり、HttpContextの作成をTwitterBusinessに移動します。構成する必要がある引数(おそらくURL)はTwitterBusinessに注入できます。このようにTwitterBusinessHttpClientの作成と処分を完全に制御しており、変更するだけの興味深いもの(URL)を注入します。

+1

ありがとうSteven。私はすべてのHttpClientインスタンスがシングルトンであることを忘れていたので、TwitterのHttpClientインスタンスはアプリケーションの寿命とともに再利用されます。私は常に静的変数を避ける傾向がありますが、私はTwitterBusiness内の静的変数としてそれを持つことができ、コンストラクタでnullの場合は一度だけ初期化すると思います。どう思いますか?ユニットテストでは、HttpMessageHandlerをコンストラクタに渡すことができます。 – raRaRa

+0

@raRaRa TwitterBusinessをステートレス(通常はそうすべき)の場合に備えて、シングルトンとして登録することさえできます。これは、あなたのhttpclientがまだインスタンス変数であることを意味しますが、私はHttpClientがスレッドセーフではないと思います。だから、それをあらゆるmrthodの中に作ることは最も安全でしょう。 – Steven

+0

スレッドセーフなので、できるだけ再利用する必要があります。だから私はそれをシングルトンにしたい。それ以外の場合は、TwitterBusinessでHttpClientのインスタンスをオンデマンドで作成します。しかし、間違いなく、TwitterBusinessはシングルトンとして登録することができます。私はこれを考え、決断を下すつもりです。助けてくれてありがとう! :) – raRaRa

関連する問題