依存性を注入せよ
Dependecy Injectionに使うXMLファイルを考えてみる。
.NETは標準で実行アセンブリに添付できるApp.configというXMLファイルを各種設定に用いており、ファィルを新たに起こす必要は無い。基本的にはApp.config中に独自なセクションとしてDI用の記述を追加することにしよう。肝心のファイルの構造(というかXMLとしての構造)だけどいろいろな例を見てみたけど、シンプルなのがいいな。
いろいろ見た中で一番気に入ったSeasarの設定ファイルのボキャブラリを参考にさせて頂いた。
それぞれのインジェクションで以下のように使う予定
・コンストラクタインジェクション
Argument
特徴的なのはassembly属性。.NETなのでクラスの属するアセンブリを指定する。
自分の書いたクラスであればこれでいいんだけど、GACに配置されているアセンブリやStrongNameのついたアセンブリのクラスを使用する場合は厳密な名前を指定する必要がある。
Assembly.LoadWithPartialNameメソッドを使えば部分名だけでもアセンブリのロードは出来るのだけれど、.NET2.0ではβ1で既にObsoleteなので使っちゃいけないってことだ。んなもんで例えばSystem.DataネームスペースのDataSetをインジェクトするならこんな感じかな。
class="System.Data.DataSet" assembly="System.Data, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
argエレメントでコンストラクタの引数を指定する。Argumentが引用符で括られている場合は文字列とし、それ以外は設定中に記述された他のコンポーネントへの参照を表すようにする。
instance属性は生成するインスタンスのスコープを記述。ASP.NETからの使用は考慮していないので、毎回インスタンスを生成する"prototype"といつも同じインスタンスを参照するsingleton、あと時間があれば.NET特有のリモーティング用のスコープも用意したいな。
・セッタインジェクション
Argument1 Argument2
こんな感じにしようと思ったけど.NETの場合セッタインジェクションは独立して必要なのかどうか..
仮にプロパティによるインジェクションを以下のように書けるとすると
・プロパティインジェクション
PropertyValue
.NETの場合はプロパティの内部実装はインスタンスメソッドなので、あえてセッタインジェクションは
いらない気がする。内部ではProperty要素のname属性をメソッドとプロパティの両側から探して見つかった方へ値を注入してやればよさげ。んなもんでセッタインジェクションを独立させるか否かは実装してから決めよう。
とりあえずキモ部分の実装が完了すればアプリケーション内では以下のイディオムでコンポーネントを
取り出すことができるようになる。
コンテナインスタンスの取得(コンテナ自体をsingletonとして登録しておくのもありかな) ComponentContainer cc = ComponentContainer.Instance; 設定ファイルのname属性を使ってコンポーネントの取得 FooClass foo = (FooClass )cc.GetComponent("FooComponent"); クラス名で取り出すことも可能 FooClass foo = (FooClass )cc.GetComponent("Framework.FooClass"); 当然ながらインタフェースで取得するほうがそれっぽいし望ましい(テストが楽になる) IFoo foo = (IFoo)cc.GetComponent("FooComponent");
こんな感じかな。Genericsを使えばキャストは不要になるけど結局 cc.GetComponent