Unityその2

コンストラクタ/プロパティインジェクションを実験君。
まずは、インジェクションされるクラスを用意します。

using Microsoft.Practices.Unity;

public class ConstructorGreetingUser
{
    IGreeting greeting;

    public ConstructorGreetingUser(IGreeting greeting)
    {
        this.greeting = greeting;
    }

    public void Say(string msg)
    {
        greeting.Say("Constructor:" + msg);
    }
}

public class PropertyGreetingUser
{
    IGreeting greeting;

    [Dependency]
    public IGreeting Greeting
    {
        get { return greeting; }
        set { greeting = value; }
    }


    public void Say(string msg)
    {
        greeting.Say("Property:" + msg);
    }
}

これをコンパイルしてGreetingUser.dllを作成します。ConstructorGreetingUserクラスはコンストラクタの引数がIGreetingなっていて、ここにインジェクションされます。一方、PropertyGreetingUserは、Greetingプロパティにカスタム属性が付いていることに気づきましたでしょうか。Unityはプロパティインジェクションをするためには、カスタム属性を付ける必要があるようです。(将来的には無くても出来るような記事をネットで見た気がしますが、失念)。あとは、設定ファイルを書いてインジェクションですが、XMLを書くのも面倒なのでIronPythonでやってしまうことにします。

import clr
clr.AddReference('Microsoft.Practices.Unity')
clr.AddReference('IGreeting')
clr.AddReference('GreetingImpl')
clr.AddReference('GreetingUser')
import IGreeting
import GreetingImpl
import ConstructorGreetingUser
import PropertyGreetingUser

from Microsoft.Practices.Unity import *

# コンテナの生成
container = UnityContainer()
# 設定ファイルではなくIronPythonコードでコンテナの設定を行う
container.RegisterType[IGreeting, GreetingImpl]()

# コンストラク インジェクション
ctor = container.Resolve[ConstructorGreetingUser]()
ctor.Say('Taro')
# プロパティ インジェクション
prop = container.Resolve[PropertyGreetingUser]()
prop.Say('Hanako')


# IronPythonで実装クラスを作成してみる
class PyGreetingImpl(IGreeting):
    def Say(self, msg):
        print 'Py,', msg

# 新たにコンテナを生成
container = UnityContainer()
# IronPtyhonのクラスはRegisterTypeでは登録出来ない
#container.RegisterType[IGreeting, PyGreetingImpl]()

# インスタンスを作成してRegisterInstanceを使うとIronPythonクラスが登録可能
# ただしインタフェースを実装する場合のみ
pygreeting = PyGreetingImpl()
container.RegisterInstance[IGreeting](pygreeting)

ctor = container.Resolve[ConstructorGreetingUser]()
ctor.Say('Taro')
prop = container.Resolve[PropertyGreetingUser]()
prop.Say('Hanako')

# 結果
# Hi, Constructor:Taro
# Hi, Property:Hanako
# Py, Constructor:Taro
# Py, Property:Hanako

こんな感じ。設定ファイルを使うのは、コンパイルせずに変更したいというのが動機のほとんどなので、スクリプト言語が使えるのなら、XMLでちまちか設定を書くよりもコードで書いてしまった方が楽な気がしますが、そんなことありません?(^^;

個人的には全てを静的言語or動的言語にするより、お互いの得意分野で補完しあうのが良い気がします。例えば、C#を使ってきっちりとしたコンポーネントを作成し、DIコンテナとスクリプト言語を使ってオブジェクトの生成と依存関係の解決をさせるとか。