旧式の方法に戻ってください。 私の答えは簡単です。 DIには、あなたが言及したすべての理由で多くの利点があります。
私は、多くの場合、私はあなたがこれをやっている場合は、サービス要件、いくつかのクラスコンストラクタによって Reused Abstractions Principle (RAP)
に違反する可能性があるインタフェース酒
ためのインタフェースを作成していますように感じます を非常に大きくすることができます。これは、IoCが使用されていない他の コンテキストでクラスを完全に無駄にします。 Single Reponsibility Principle:あなたのクラスのコンストラクタが大きすぎると複雑な場合
が、これはあなたが非常に重要な他の原則に違反していることをお見せするための最良の方法です。この場合は、コードを別のクラスに抽出してリファクタリングする必要があります。依存関係の数は約4です。
DIを実行するには、インタフェースを使用する必要はありません。オブジェクトへの依存関係を取得します。インタフェースを作成することは、テスト目的のために依存関係を代用できる必要があります。 依存のオブジェクトがある場合を除き:
- 簡単
- は、外部サブシステム(ファイルシステム など)に話をしない隔離する
あなたは抽象クラスとして、あなたの依存関係を作成することができ、またはあなたが代用したいメソッドが仮想である任意のクラス。しかし、インタフェースは、依存関係の最良の分離された方法を作成します。
実行時に新しいエンティティをインスタンス化する場合、 はインスタンスを作成するためにIoCコンテナ/カーネルにアクセスする必要があります。 これは、IoCコンテナ自体(NinjectのカーネルのインスタンスであるObjectFactory SM)に依存します。実際には となります。どうすれば 解決できますか?抽象的なファクトリが気になりますが、それだけに はコードを複雑にします。
IOCコンテナへの依存関係は、クライアントクラスに依存することは決してありません。 そして、彼らはする必要はありません。
最初に依存性注入を正しく使用するには、Composition Rootの概念を理解することが重要です。これは、コンテナを参照する必要がある唯一の場所です。この時点で、オブジェクトグラフ全体が構築されます。これを理解すると、クライアントにコンテナが必要ないことが分かります。各クライアントは依存関係が注入されるだけです。
new SomeBusinessObject(
new SomethingChangedNotificationService(new EmailErrorHandler()),
new EmailErrorHandler(),
new MyDao(new EmailErrorHandler()));
あなたはどのように知っている具体的な工場を作成することができます。 は、あなたがこのような多くの依存関係を持つオブジェクトを構築したいと言う:
は建設を容易にするために、あなたが従うことができ、他の多くの生成に関するパターンもあります。この構築:
public static class SomeBusinessObjectFactory
{
public static SomeBusinessObject Create()
{
return new SomeBusinessObject(
new SomethingChangedNotificationService(new EmailErrorHandler()),
new EmailErrorHandler(),
new MyDao(new EmailErrorHandler()));
}
}
をし、このようにそれを使用します。
SomeBusinessObject bo = SomeBusinessObjectFactory.Create();
また、貧しいマンジを使用し、すべての引数を取らないコンストラクタを作成することができます:それは働いていたよう
public SomeBusinessObject()
{
var errorHandler = new EmailErrorHandler();
var dao = new MyDao(errorHandler);
var notificationService = new SomethingChangedNotificationService(errorHandler);
Initialize(notificationService, errorHandler, dao);
}
protected void Initialize(
INotificationService notifcationService,
IErrorHandler errorHandler,
MyDao dao)
{
this._NotificationService = notifcationService;
this._ErrorHandler = errorHandler;
this._Dao = dao;
}
そして、それはちょうどようだ:
貧者のDIを使用して
SomeBusinessObject bo = new SomeBusinessObject();
が考えられています既定の実装が外部のサードパーティのライブラリにある場合は悪いが、適切な既定の実装を行うと悪くなりません。
明らかに、すべてのDIコンテナ、オブジェクトビルダーおよび他のパターンがあります。
あなたが必要とするのは、あなたのオブジェクトの良い創造性のパターンを考えることだけです。オブジェクト自体は依存関係の作成方法に気を付けるべきではなく、実際には複雑になり、2種類のロジックを混在させます。だから私はDIを使用して信じていない生産性の損失を持つ必要があります。
オブジェクトにインスタンスを1つだけ注入できない特殊なケースがいくつかあります。寿命が一般的に短く、オンザフライのインスタンスが必要な場合。この場合、あなたは依存関係としてオブジェクトに工場を注入する必要があります
public interface IDataAccessFactory
{
TDao Create<TDao>();
}
あなたはこのバージョンを気づくことができるとして、それは、様々なタイプを作成するためにIoCコンテナを利用することができますので、(IoCコンテナかかわらず、注意してください一般的なものであり私のクライアントにはまだ見えません)。
public class ConcreteDataAccessFactory : IDataAccessFactory
{
private readonly IocContainer _Container;
public ConcreteDataAccessFactory(IocContainer container)
{
this._Container = container;
}
public TDao Create<TDao>()
{
return (TDao)Activator.CreateInstance(typeof(TDao),
this._Container.Resolve<Dependency1>(),
this._Container.Resolve<Dependency2>())
}
}
私は、これは、工場は、オブジェクトの新しいインスタンスを作成する必要があり、ちょうどコンテナが対象得るような新しいインスタンスを提供すると仮定していないことに注意することが重要である、私はIoCコンテナを持っていたにもかかわらず、アクチベーターを使用お知らせ異なる生涯(Singleton、ThreadLocalなど)で登録することができます。ただし、使用しているコンテナによっては、これらの工場を生成できるものもあります。しかし、オブジェクトが一時的な有効期間で登録されていることが確実であれば、それを解決するだけで済みます。
EDIT:抽象工場の依存関係を持つクラスを追加:
public class SomeOtherBusinessObject
{
private IDataAccessFactory _DataAccessFactory;
public SomeOtherBusinessObject(
IDataAccessFactory dataAccessFactory,
INotificationService notifcationService,
IErrorHandler errorHandler)
{
this._DataAccessFactory = dataAccessFactory;
}
public void DoSomething()
{
for (int i = 0; i < 10; i++)
{
using (var dao = this._DataAccessFactory.Create<MyDao>())
{
// work with dao
// Console.WriteLine(
// "Working with dao: " + dao.GetHashCode().ToString());
}
}
}
}
は、基本的にDI/IoCのは劇的に私の生産性が遅くなり いくつかのケースでは、さらにコードやアーキテクチャ
マークを複雑にすることSeemanはこの件に関するすばらしいブログを書いて、質問に答えました: このような質問に対する私の最初の反応は、疎結合コードが理解しにくいということです。何よりも難しい?
Loose Coupling and the Big Picture
EDIT:あなたが使用しているが実際の依存関係を考慮すると最終的に私はいないすべてのオブジェクトと依存必要があることを指摘したいと思いますか、依存関係を注入する必要があり、最初に考慮してください。
何依存関係ですか?
- アプリケーション設定
- システムリソース(時計)
- サードパーティのライブラリ
- データベース
- WCF /ネットワークサービス
- 外部システム(ファイル/メール)
どれでも上記のオブジェクトまたは共同作業者のうち、あなたのコントロールから外れて、サイドEFを引き起こす可能性があります行動の善し悪しと違いがあり、テストするのが難しくなります。これらは、抽象化(クラス/インタフェース)を検討し、DIを使用する時代です。
依存関係はありませんが、本当にDIは必要ありませんか?
List<T>
- のMemoryStream
- 弦楽器/プリミティブ例えば必要な場合、上記単に
new
キーワードを使用してインスタンス化することができるよう
- リーフオブジェクト/ DTOの
オブジェクト。特定の理由がない限り、このような単純なオブジェクトにはDIを使用することを推奨しません。オブジェクトが完全に制御されているかどうか、またオブジェクトグラフや副作用が発生していないかどうかを検討してください。この場合、単にそれらを新しいものにしてください。
私はMark Seemanの投稿へのリンクを多く投稿しましたが、彼の書籍やブログの投稿を読むことをお勧めします。
非常に良い返信、トピックの上に、ありがとう!あなたがリンクしている両方の記事を読んでいます。両方とも、情報の大きなソースであり、実際に私が気づいた他の多くの質問に答えました。 RAP違反とSRPは、私の場合に留意すべき良い事柄として際立っています。クライアントからIoCコンテナを隠すために抽象ファクトリを使用すると言いますが、抽象的なファクトリがIoCコンテナに依存するのは大丈夫ですか? – edvaldig
ありがとう、私はこれがあなたを助けてくれてうれしいです、そして、私はそう言っています。これは、抽象的な工場がコンテナについて知ることは非常に容認しています。工場はコンポジットルートと同じレイヤーで動作し、ビジネスロジックを含み、単に具体的なインスタンスを管理するだけです。テスト環境では、Iocコンテナを使用しない場合もありますが、コンクリートタイプが異なるため、異なるファクトリが必要になります – Andre
こんにちは、私は依存関係が何であるかを理解するための最後の編集を追加しました。シンプルで必要のないオブジェクトの依存関係管理を心配する必要があります。 – Andre