2

次のクラスがあり、後者のサービスクラスは特定のコンテナーに結合されていますが、前者を使用する場合、コントローラークラスがサービスクラスを使用するのではなく、サービスクラスの依存関係を注入し、依存関係を解決するためにサービスクラスに任せる必要があるのはなぜですか?

public class ProfileController {

    public ProfileController(IProfileService profileService, IProfileRepository  profileRepository, IUnitOfWork unitOfWork, IDatabaseFactory databaseFactory) {
    profileService.Get();
    }
}

public class ProfileService:IProfileService {

    public ProfileService(IProfileRepository  profileRepository, IUnitOfWork unitOfWork, IDatabaseFactory databaseFactory) {
    profileService.Get();
    }  
}

また

public class ProfileController {
    public ProfileController(IProfileService profileService) {
                            profileService.Get();
    }
}

public class ProfileService:IProfileService {

    public ProfileService() { 
        var dbfactory=container.Resolve<IDatabaseFactory>();
        var unitofwork=container.Resolve<IUnitofWork>();
        var rep=container.Resolve<IProfileRepository>();
        rep.Get();
    }  
}
4

2 に答える 2

1

サービス クラスは、その依存関係を解決するべきではありません。したがって、オプション 1 を使用する必要があります。インスタンスは、DI コンテナーに完全に依存しない必要があります。

なんで?

関心の分離: 依存性注入の大きなアイデアは、オブジェクトのインスタンス化を、単一の場所 (コンテナー) で処理される個別の関心と見なすことです。インスタンスを作成し、インスタンス間の参照を設定するのはコンテナの仕事です。インスタンス自体にコンテナーを使用させると、概念が損なわれます。

モジュール クラスの再利用性: DI コンテナーを「使用する」クラスがある場合、別の DI フレームワークを含む別のアーキテクチャでこのクラスを変更せずに使用することはできません。したくないかもしれませんが、正当な理由もなく自分を制限します。

セマンティックな明快さ: コンストラクターのパラメーターは、次の質問に答える必要があります: そのクラスのインスタンスを作成するには何が必要ですか。あなたの場合、これは stuff:IDatabaseFactoryなどであり、何もありません ( ())。

テスト容易性: クラスで DI インフラストラクチャ全体が機能する必要はありません。おそらくテストの理由で、モックアップが実行されるべきであり、実行時に DI コンテナーによって行われることです。これは「再利用性」につながります。

すぐに失敗する: 依存関係が解決できないと仮定した場合: クラスのインスタンス化時ではなく、コンテナーのビルド時に例外がスローされると便利です。

まとめ

container.Resolve(...)

モジュールでは発生しないはずです。

于 2013-03-13T14:28:33.790 に答える
0

どちらの例も軌道に乗っていないように感じます。

提案された解決策:

public class ProfileService:IProfileService {

  public ProfileService(IProfileRepository  profileRepository, IUnitOfWork unitOfWork, IDatabaseFactory databaseFactory) {

  }  
}

次の方法で、呼び出し元でそのサービスを使用します。

public class ProfileController {
  [ConstructorInjection]
  public ProfileController(IProfileService profileService) {

  }
}

または

public class ProfileController {
  public ProfileController(IProfileService profileService) {

  }
}

また

public class ProfileController {

  public ProfileController() {
       this.service = resolveFromContainer.Get<IProfileService>();
  }
}

また

public class ProfileController {

  public ProfileController() {
       this.service = new ServiceFactory.get<IProfileService>()
  }
}

(1)。上記のいずれの場合でも、関心の分離が問題になるとは思いません。コントローラはリポジトリ ジョブを実行していません。使用するリポジトリを提供するだけです。

モジュールの公開に関する限り。共有アセンブリの場合、呼び出し元に di コンテナーの使用を強制するべきではないことに 100% 同意します。

ただし、共有コードを作成して、消費するアプリケーションに共有モジュールの依存関係を注入する方法を選択させることができます。

(2).Marc は、彼の回答でこれについて言及しています。 (())。」

私は 100% 同意しますが、コントローラー コンストラクターが表示されている場合は。サービスだけでなく、他にもたくさんあります。コントローラーが機能するために他に必要なものはありますか? これはアプリケーション固有の質問であり、回答を一般化することはできません。サービスが機能するだけでよい場合は、それを渡します。コントローラーを定義しないため、サービスの依存関係を渡さないでください。サービスを定義します。

リポジトリを渡すことは、開発者キーをライブラリに渡すこととは異なります。リポジトリを提供する柔軟性を許可していますが、宛先も指定しています。これは場合によっては便利です。ログ情報を格納するライブラリ (格納場所を指定しています) も、コードが抽象化されている RequestProcessor パターンで役立ちます。

Q: あなたのサービスが保存して戻ることを期待している場合、レポジトリ dbFactory をそれに渡すのは正しいですか?

上記の新しいソリューションで。プロファイル サービス コードは変更されません。プロファイル サービスには DB、リポジトリが必要な場合がありますが、コントローラが機能するには、リポジトリ、ファクトリ、サービスのすべてが必要ですか? これはアプリケーション固有です

* Q: 渡されたパラメーターは、コントローラーを作成するために必要ですか、それとも、その下に他の依存関係を作成するために間接的に使用されているものがありますか? *

(3) 「あなたのモジュールでは、container.Resolve(...) は発生しないはずです。」

* Q:あなたが参照するモジュールは何ですか? DI コンテナーを使用する必要があるが、コードのどの部分でも DI 属性/解決メソッド/依存関係構成を使用することを決して選択しないと言っているのですか? *

(di container の作成者がその考えにうんざりしているのを見ることができます)

Q:resolve メソッドを使用してもよい場所はどこですか?

共有コードで解決メソッドを使用しないことに 100% 同意します。ただし、コントローラーはアプリケーション固有のコードと同様に実行でき、依存関係を注入/アセンブルするためにコンテナーが必要です。

DI コンテナーは、アプリケーション設計の第一級市民であるコア フレームワークです。構築する DI コンテナーを 1 つも選択していない場合、本当に DI を採用したのでしょうか?

DI コンテナーが .NET ライブラリのような第一級市民である場合、追加の作業なしにコンテナーを変更することを「計画」することは決してありません。DI コンテナーを簡単に切り替えることができるコードを探すのは大変な作業であり、Microsoft/コミュニティに解決を任せるのが最善です。

要約: 私は回答に関する Marc の考えのほとんどに同意します*ただし、どちらのソリューション提案の回答も、彼が提起したすべての質問に正しく回答するわけではありません。*

参考文献:

  1. http://martinfowler.com/articles/injection.html
  2. http://msdn.microsoft.com/en-us/magazine/dd882510.aspx

軽微な不満: Unit of Work/Respository の使用に関する上記のいずれかのソリューションに関する小さなコメント

上記のリンクから引用されたコード。public void RunCommands(請求書) { IUnitOfWork unitOfWork = _unitOfWorkFactory.StartNew();

UnitOfWorkfactory はデータベース ファクトリを管理する必要があり、それをサービスに渡すべきではありません。

私見では

私たちは、私には正しくないと感じる依存関係の同じハンドホールディングを行っています。同じことがリポジトリ ファクトリにも当てはまります。

ファクトリは、db コンテキストなどのようなコンテキストを設定する必要があります。その責任は、サービスにもありません。

これはより良いインターフェース public ProfileService(IProfileRepository profileRepository, IUnitOfWork unitOfWork) かもしれません

于 2013-03-13T18:44:58.290 に答える