8

いくつかのグローバルコンポーネントがあり、それらを設計に組み込む方法がわかりません。そのような:

  • 設定クラス:プログラムの初期設定とのインターフェースであり、app.config(1way)、web.config(1way)、ハードコードされた値(1way)、またはsqldb(2way)の舞台裏である可能性があります。

  • 言語クラス:さまざまな言語セットが含まれています。また、resxファイル(1way)、ハードコードされた値(1way)、またはsqldb(2way)が背後にある可能性があります。

最初の質問は、依存性注入でこれらのクラスをセッタープロパティにする必要があるかどうかです(私はWindsorを使用しています):

public ISettings Settings {set;}
public ILanguage Language {set;}

または、それらをアンビエントコンテキストにする必要があります。

string DoSomethingAndReportIt() {
    //do something ...
    var param = Settings.Current.SomeParam;
    //report it ...
    return Language.Current.SomeClass_SomeMethod_Job_Done;
}

.netライブラリには、実際にアンビエントコンテキストパターンを使用するコンポーネントがいくつかあることに気付きました。たとえば、System.Security.Principal、System.Web.ProfileBase、System.Thread.CurrentCulture ...

SettingsやLanguageなどのグローバルクラスをアンビエントコンテキストクラスにすることは害ではないと思いますか?そうでない場合、なぜDIが優先されるのですか?ユニットテストでは、アンビエントと比較してより多くの利点がありますか?

2番目の質問は、DIの方が優れている場合(DIパターンが好ましいと感じています)、Security.PrincipalやProfileなどの既存のアンビエントクラスをプロキシしてDIパターンに従うための良い方法は何ですか?

4

1 に答える 1

3

複数のレイヤーにまたがる機能を実装する必要がある場合は、アンビエントコンテキストで問題ありません。(あなたの場合、2つのオブジェクトはグローバルであると言います)この機能は横断的関心事として知られています。お気づきのように、.NETの多くのクラスは、のようにアンビエントコンテキストIPrincipalとして実装されています。アンビエントコンテキストの実装の動作バージョンを取得するには、アンビエントコンテキストとして開発されている場合Settings、オブジェクトにデフォルト値を提供する必要があります。Language私の仮定は、とのデフォルトの実装を提供することでILanguageありISettings、それらをグローバルに使用することを考えると、それらはアンビエントコンテキストの適切な候補です。

一方、これら2つのインターフェイスを実装するオブジェクトをどのくらいの頻度で使用する予定ですか。そして、意味Settings != nullとという2つのオブジェクトの存在は重要Language != nullですか?それらを1つまたは2つのクラスで実際に使用する場合、および/またはオブジェクトの存在がそれほど重要でない場合は、セッターインジェクションを使用することをお勧めします。セッターインジェクションは実際にはデフォルト値を必要としないため、オブジェクトは。にすることができますnull

個人的には、私はアンビエントコンテキストのファンではありません。ただし、それが最も受け入れられる解決策であることが判明した場合は、それを使用します。あなたの実装の場合、私はこのようなことをします:2つのインターフェースを1回だけ1つの場所に実装するオブジェクトを初期化する必要があるので、アンビエントコンテキストから始めることができます。非常に少数の場所で使用していることに気付いた場合は、セッターインジェクションとしてリファクタリングすることを検討してください。オブジェクトの存在が重要な場合は、コンストラクターインジェクションの実装について考えてください。

于 2012-07-26T13:32:12.180 に答える