私はStructureMapの使い方の一部を理解するのに苦労しています。代わりのコンストラクタインジェクションとサービスロケータの使用
public ShippingScreenPresenter()
{
_service = ObjectFactory.GetInstance<IShippingService>();
_repository = ObjectFactory.GetInstance<IRepository>();
}
:特に は、ドキュメント内のステートメントは、一般的なアンチパターン、サービスロケータとしてのStructureMapの使用のみの代わりにコンストラクタインジェクション(ストレートのStructureMapドキュメントからコードサンプル)について行われます。
public ShippingScreenPresenter(IShippingService service, IRepository repository)
{
_service = service;
_repository = repository;
}
これは非常に短いオブジェクトグラフのための罰金ですが、多くのレベルの深さのオブジェクトを扱うとき、これはあなたが右の上から深いオブジェクトによって必要なすべての依存関係を伝承すべきであることを意味していますか?確かにこれはカプセル化を破り、より深いオブジェクトの実装に関する情報をあまりにも多く公開します。
アクティブレコードパターンを使用しているため、自分のレコードがデータリポジトリにアクセスして、自分自身を保存して読み込む必要があるとします。このレコードがオブジェクト内にロードされている場合、そのオブジェクトはObjectFactory.CreateInstance()を呼び出して、アクティブなレコードのコンストラクタに渡しますか?そのオブジェクトが別のオブジェクトの内部にある場合はどうなりますか? IRepositoryをそれ自身のパラメータとしてさらに上から取り入れますか?これは、現時点でデータリポジトリにアクセスしているという事実を親オブジェクトに示します。外部オブジェクトはおそらく知ってはならないものです。
public class OuterClass
{
public OuterClass(IRepository repository)
{
// Why should I know that ThingThatNeedsRecord needs a repository?
// that smells like exposed implementation to me, especially since
// ThingThatNeedsRecord doesn't use the repo itself, but passes it
// to the record.
// Also where do I create repository? Have to instantiate it somewhere
// up the chain of objects
ThingThatNeedsRecord thing = new ThingThatNeedsRecord(repository);
thing.GetAnswer("question");
}
}
public class ThingThatNeedsRecord
{
public ThingThatNeedsRecord(IRepository repository)
{
this.repository = repository;
}
public string GetAnswer(string someParam)
{
// create activeRecord(s) and process, returning some result
// part of which contains:
ActiveRecord record = new ActiveRecord(repository, key);
}
private IRepository repository;
}
public class ActiveRecord
{
public ActiveRecord(IRepository repository)
{
this.repository = repository;
}
public ActiveRecord(IRepository repository, int primaryKey);
{
this.repositry = repository;
Load(primaryKey);
}
public void Save();
private void Load(int primaryKey)
{
this.primaryKey = primaryKey;
// access the database via the repository and set someData
}
private IRepository repository;
private int primaryKey;
private string someData;
}
どのような考えにも感謝します。
サイモン
EDIT: 意見は、注入が最上層に開始すべきであるということのようです。 ActiveRecordは、OuterClassに注入されるThingThatNeedsRecordに注入されます。 この問題は、ActiveRecordを実行時パラメータ(たとえば取得するレコードのID)でインスタンス化する必要がある場合に発生します。 ActiveRecordをトップに置くと、何とかその位置にある必要があるIDを把握しなければなりません(トップレイヤを実装すべきでない実装に公開する)か、または部分的に構築されたActiveRecordを持たなければなりません後でIdを設定してください。これは、Nレコードが必要な場合にはさらに複雑になり、ThingThatNeedsRecordの内部でロジックが実行されるまではわかりません。
可能な重複:http://stackoverflow.com/questions/4570750/dependency-injection-turtles-all-the-way-down –
関連:http://stackoverflow.com/questions/2420193/dependency-injection-コンストラクタ - 狂気/ 2420245#2420245 –