依存性解決の方向
Sesar2(s2dotnet)の実装を見ていてふと思ったのだけど以下のように3つのdiconをインクルードするroot.diconが構成されていた場合
root.dicon
bar1 bar1.dicon
foo bar2.dicon
foo bar3.dicon
foo
DIコンテナは以下のようなdiconの定義から構成されるコンポジションになるはずだ。
root.dicon ├── bar1.dicon ├── bar2.dicon └── bar3.dicon
このようなdiconの構造を持つDIコンテナに対してコンポーネントの検索を行うと、DIコンテナはコンポーネント定義をroot.dicon->bar1.dicon->bar2.dicon->bar3.diconの順で検索してそのインスタンスを生成し依存関係を解決しようとする。
ここまでは当たり前の話だが、疑問なのはコンテナ"root"はインクルードしたコンテナ"bar1〜bar3"も依存関係の解決の対象にするが、逆にコンテナ"bar1〜bar3"は親である"root"を依存関係を解決する対象にしていない、ということ。これはSesar2のドキュメントに明記されていることなので仕様通りなのだけど、何故Sesar2は親のコンテナを依存性解決の対象から外したのだろうか。
diconを分割できる、ということはコンポーネントの依存関係が複数のdiconを横断する可能性があるということになる。例えば上の例ではbar1.dicon内でコンポーネント"bar1"のコンストラクタインジェクションの為のarg要素で指定した名前"foo"は、root.diconで定義されているコンポーネント"foo"を参照することを期待する場合などだ。しかし現状の仕様では親のroot.diconは検索の対象外のためコンポーネント"foo"の依存関係は解決できない。
とここまで書いていて気がついた。Sesar2はインクルード対象となる子(child)のdiconはDIコンテナ間で共有する可能性があることを前提に考えているのだろうか。
parent1.dicon └─────────┐ parent2.dicon │ ├── bar1.dicon ─┤ ├── bar2.dicon ─┤ └── bar3.dicon ─┘
このような構造の場合、親は一つではないので例えばコンテナ"bar1"は親のコンテナを特定することができない訳だ。
俺様仕様でDIContainerにparentプロパティを付けて子->親の依存性解決を可能にしようか、と思っていたのだけれどそう単純にはいかないか。
追記1:
依存性解決の方向を両方向(親->子、子->親)にしない理由はもっと単純だろうと思います。というのも実際にparentプロパティを追加して試してみたのですがこれって普通に実装すると簡単に参照の再帰を引き起こします。 orz...
追記2:
参照の再帰を起こしてしまう問題は親のコンテナを検索する際はコンポジションを処理せずに自身のコンテナだけを対象にするように書換えることで解決可能。しかし解決したとしてもやはり親のコンテナが複数存在していた場合、最後にインクルードされた親だけしか認識することができないのであまり実用的ではないかも。複数のdiconに分割する際は依存関係を持つコンポーネント同士はできるだけ一つのdiconにまとめたほうがすっきりするし問題の発生を防ぐという意味でそのほうが良いね。