2009-09-07 11 views
3

私は、コンストラクタインジェクションに基づいて、自分の依存性注入コンテナをPHPでハックしようとしています。コンテナは複雑なオブジェクトをインスタンス化し、リフレクションを使用してコンストラクタの型ヒントに基づいて必要なオブジェクトを注入します。DIコンテナ:同じタイプのコレクションから適切なコンポーネントを注入しますか?

私が明らかに遭遇したことは、同じタイプ(同じクラスを拡張/同じインターフェースを実装する)で注入できる複数のコンポーネントを登録できるという事実です。たとえば、2つのオブジェクトの両方がIteratorインタフェースを実装する別個のオブジェクトを必要とする場合はどうでしょうか? DIコンテナはこれをどう扱うのですか?複雑なオブジェクトのどれに注入する必要があるか、あいまいなインターフェイスを持つオブジェクトのどちらをコンテナに決定させるかをコンテナに任せますか?

または、1つのタイプの複雑なオブジェクトの作成を担当する単一のDIコンテナのみですか?換言すると、各複合オブジェクトが異なるDIコンテナをインスタンス化するためである。私はこれが意図だとはほとんど想像できません。

+0

"php"というタグは削除されました。これは実装言語の選択肢が本当に問題には関係ないからです。 – skaffman

答えて

1

あなたが記述しているのは、DI自体ではなく、むしろオートワイヤリングです。通常、DIではどのコンポーネントを何に接続するかを明示的に設定します。

DIは、指定されたタイプ(DAOなど)の実現可能なインプリメンテーションが1つのみの粗いコンポーネントでは本当に望ましいものです。型があいまいである場合、そのうちの1つを「プライマリ」としてマークするか、他のものを「候補外」とマークするか、必要なコンポーネントの名前を明示的にマークします。

は、それが助け場合は、春には、あなたの質問で何を意味するかに応じて、オートワイヤリングherehere

+0

Skaffman、説明をいただきありがとうございます。私はこれがautowiringとして知られていたのか分からなかった。しかし、それは賢明だと思う。私はあなたが最後に提案したオプションを持って行くべきだと思います。なぜなら、他のオプションはおそらく長期的には望ましくない影響を引き起こすからです。私はできるだけ多くの弾丸にしようとしています。ふりだしに戻る。 :) –

+0

PHP用の既存のIoCフレームワークが必要ですか? – skaffman

+0

あなたはおそらく正しいでしょう。しかし、私は通常、これらのことを自分自身でやってみたい(後で既存の解決策に落ちる;-)、それが何を必要とするのかをよりよく理解するのを助ける。また、私はOOPスキルを向上させ、運動のためにこれを好きです。 :) 追加情報のおかげでBTW。最初のものは、あなたが与えたオプションとそれから得た結論を与えるもので、解決できないあいまいさがあれば例外を投げる必要があります。 –

1

を処理する方法にまで読むことができる、ここでGuiceのは(Java用DIフレームワーク)を使用しています何:

の場合Fooの注入要求があるたびに異なるオブジェクトが必要な場合は、アプリケーションを配線するときにFoo.classを特定のインスタンスFooにバインドせず、必要に応じてFooを作成するオブジェクトであるProvider<Foo>をバインドします。そして、Fooが注入された場所はすべて新しいインスタンスを取得します。たとえば、Fooインスタンスの代わりにFooをクラスにバインドするだけの場合(Fooがインターフェイスで、Fooを実装するクラスであるRealFoo.classにバインドした場合)、同じ効果が得られます。毎回新しいインスタンスが作成されます。 Fooの2つのインスタンスが必要な場合は、アプリケーションを配線してから、アプリケーションを配線するときに構成する必要があります(これはデフォルトの「スコープなし」の動作です)。 "このFooのインスタンスは、Bumbleを作成するときに使用されるのに対して、Bazの場合はまたはBazを作成するときに使用されます。"と言うと、注入ポイントに注釈を付けてから、アプリケーションを配線するときは

Foo foo1 = new Foo("1"); 
Foo foo2 = new Foo("2"); 
bind(Foo.class).annotatedWith(Names.named("Bar")).toInstance(foo1); 
bind(Foo.class).annotatedWith(Names.named("Baz")).toInstance(foo1); 
bind(Foo.class).annotatedWith(Names.named("Bumble")).toInstance(foo2); 

ここでは、引数をBarのconstrucに注釈したと仮定しますBazBumbleため

public Bar(@Named("Bar") Foo foo) { ... 

と同様:ようなものでTOR。もちろん、BarBazというコンストラクタに同じものをアノテーションする場合は、bindのいずれかの行をスキップできます。

私は、リフレクションに基づいたPHP用のアノテーション処理フレームワークがあることを知っています。あるいは、おそらく引数名に基づいた規約を使用することができます。

+0

O、それは私が心に留めていたよりもさらに複雑な実装です。私はまだ同じオブジェクトが異なる注射でインスタンス化されていることについて心配していませんでした(まだ私の心を渡っていませんでした)。むしろ、私は同じ基本タイプまたは基本インターフェースのオブジェクトを注入する必要があるが、実際には異なるクラスである異なるオブジェクトを指していました。 (私はおそらくここで正しい用語を混ぜるために私を許します)。 しかし、あなたの例では、物事をすべて一緒に見ることができます。良い点。 :) –

+0

ところで、私は注釈オプションが好きではないかと思います。私は主語の実装を変更することなく、できるだけ「きれい」にしておきたいと思っています。私が何を意味しているか知っていれば、どんな物体でも棚の作業ができるはずです。コンストラクタの引数名、またはより良いことに、DIの構成における依存関係を明示的に命名することは、おそらく道のりです。 –

関連する問題