3

コンストラクター注入に基づいて、PHP で独自の依存性注入コンテナーをハックしようとしています。コンテナーは複雑なオブジェクトをインスタンス化し、リフレクションを使用してコンストラクターの型ヒントに基づいて必要なオブジェクトを挿入します。

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

それとも、1 つのタイプの複雑なオブジェクトの作成を担当するのは、単一の DI コンテナだけですか? つまり、複雑なオブジェクトごとに個別の DI コンテナーをインスタンス化します。これが意図されているとは想像しがたいですよね?

4

2 に答える 2

1

質問の意味に応じて、Guice(Java用のDIフレームワーク)が使用するものは次のとおりです。

のインジェクションリクエストがあるたびに個別のオブジェクトが必要な場合はFoo、アプリケーションを接続するときFoo.classに、の特定のインスタンスにバインドせずFoo、代わりに、オンデマンドProvider<Foo>を作成するオブジェクトであるをバインドします。次に、注入されFooたすべての場所が新しいインスタンスを取得します。インスタンスではなくクラスにFooバインドするだけの場合(たとえば、はインターフェイスであり、それを実装するクラスにバインドすると)、同じ効果が得られます。つまり、毎回新しいインスタンスが作成されます。(これはデフォルトの「スコープなし」の動作です。Guiceスコープの動作はこのコメントの範囲を超えています)FooFooFooRealFoo.classFoo

Fooただし、アプリケーションを接続するときに作成する2つのインスタンスが必要な場合は、「このFooのインスタンスは、Barまたはを作成するときBazに使用されますが、この他のインスタンスは、を作成するときに使用されますBumble」と言うことができます。注入ポイントに注釈を付けてから、アプリを配線するときに次のように言います。

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のコンストラクターへの引数に次のような注釈を付けたと仮定します。

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

そして同様にBazBumble。もちろん、とのコンストラクターに同じもので注釈を付ける場合はBarBaz1行をスキップできますbind

リフレクションに基づくphpのアノテーション処理フレームワークがあることは知っています。あるいは、引数名に基づく規則を使用できるかもしれません。

于 2009-09-07T23:46:35.990 に答える
1

あなたが説明しているのは、DI自体ではなく、単純なDIよりも一歩進んだ自動配線です。通常、DI では、どのコンポーネントが何に配線されるかを明示的に構成します。

Autowired DI は、指定されたタイプ (DAO など) の適切な実装が 1 つしかない、粗粒度のコンポーネントでのみ本当に望ましいものです。タイプがあいまいな場合は、そのうちの 1 つを「プライマリ」としてマークするか、他のタイプを「候補ではない」としてマークするか、必要なコンポーネントの名前で依存関係を明示的にマークします。

それが役立つ場合は、ここここでSpringが自動配線を処理する方法を読むことができます

于 2009-09-07T23:23:14.557 に答える