2016-07-13 30 views
0

依存オブジェクトをコンストラクタを介して依存する各オブジェクトに注入するのではなく、静的クラスの静的フィールドとして持つのはどうですか?依存性注入 - 各オブジェクトに注入する代わりに静的依存関係フィールドを使用する

public static class Dependencies 
{ 
    public static IUsersRepository Users; 
    ... 
} 
//Use in a method that depends on Users Repository 
var users = Dependencies.Users.GetUsers();  

VS.

public class UserController 
{ 
    private IUsersRepository _users; 
    public UserController(IUsersRepository repo) 
    { 
     this._users = repo; 
    } 
    public List<User> GetCustomUsers() 
    { 
     var users = this._users.GetUsers(); 
     ... 
    } 
} 
+0

テストプロセス中、ユーザーフィールドを偽のリポジトリに割り当てます。 – Pharaz

答えて

0

正直言って、もしあなたがそうしたら警察はあなたのドアをノックするつもりはないが、それは論理的な結論(すなわち、感知できるサイズのアプリケーション)になると、あなたは "スパゲッティコード "コードベース。

ほとんどのカップリングは、SOLID principlesのようなものです。 Dependencyクラスに密接に結合しています。理想的にDIが、オブジェクトグラフを構築し、依存関係を注入することによってこれを防ぐことができ、それらのオブジェクトがそれを提供する実装に知識を持たない(つまり結合されていない) DIコンテナとシングルトンのライフスタイルを使用している場合は、本質的にあなたが記述したもの、つまり静的フィールドを持っています。しかし、コンテナ(「コンテナレス」コンテナでも人気が高まっています)では、柔軟性が増し、難しいことはあなたのために行われます。

DIを使用する、特にコンテナ経由での使用は、おそらく悪い考えです(ロギング、新しいGuid値の生成、現在の日付の取得)。これらのいくつかのケースは、「周囲環境」ソリューションで解決できます(詳細はMatthew Watson's answerを参照)。

2

UserControllerがインスタントIUsersRepositoryと別のUserController、あなたは、静的な依存関係でこれを行うことができない、異なるIUserRepository実装のインスタンスを使用したいを使用したいと仮定します。

+0

すべてのUserControllerがIUsersRepositoryのsignleインスタンスのみを使用すると仮定しても、スタティック依存性アプローチの問題はありますか? – Pharaz

+0

いいえ、フィールド/プロパティを介して注入することで依存関係注入を破ることはありません。しかし、依存関係が固定されたオブジェクトを構築することは、オブジェクトの依存関係が存続期間中にいつでも変更される可能性があることを想定するよりも優れています。 Ambient Contextパターンの場合は –

3

「Ambient Context」と呼ばれるDIパターンがあります。これを使用してこれを行うことができます。

これは、クロスカッティングの問題を常に回避することができますが、ユニットテストのことも可能です。

public abstract class TimeProvider { 
    private static TimeProvider current = 
    DefaultTimeProvider.Instance; 

    public static TimeProvider Current { 
     get { return TimeProvider.current; } 
     set { 
     if (value == null) { 
      throw new ArgumentNullException("value"); 
     } 
     TimeProvider.current = value; 
     } 
    } 

    public abstract DateTime UtcNow { get; } 

    public static void ResetToDefault() { 
     TimeProvider.current = DefaultTimeProvider.Instance; 
    } 
} 

実装は次のようになります:

public class DefaultTimeProvider : TimeProvider { 
    private readonly static DefaultTimeProvider instance = 
     new DefaultTimeProvider(); 

    private DefaultTimeProvider() { } 

    public override DateTime UtcNow { 
     get { return DateTime.UtcNow; } 
    } 

    public static DefaultTimeProvider Instance { 
     get { return DefaultTimeProvider.instance; } 
    } 
}  

コードではなく、直接DateTimeを使用するよりも日時にアクセスするためにTimeProvider.Currentを使用する

標準的な例は、DateTimeのプロバイダです。

デフォルトの具象実装は、通常のDateTime.UtcNowを返します。ただし、単体テストでは、特別なテスト実装を使用して単体テストを実行する前にTimeProvider.Currentを設定することができます。

See this page (where that code comes from) for more information.

だけなので、上の日時、セキュリティ、ロギングととして真に横断的関心事のために、このパターンを使用する必要があります注意してください。

+0

+1ですが、それは問題の特定の解決策です。私は静的依存性アプローチの問題について尋ねました。 – Pharaz

関連する問題