技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

DI (Seaser.NET)を C# で試してみる

DI(Dependency Injection。依存注入)とかAOPAspect-Oriented Programming。アスペクト指向プログラミング)とかをC#でできると聞いてやってみた。
で、実際に利用するライブラリに関してはコレ。
Seaser.NET という、Java ではもう有名すぎるアプリケーションフレームワーク
とにかくコレをDLして、プロジェクトから参照をかける。このとき、build ディレクトリの内容もそうだが、lib ディレクトリの中の dll もコピーして置いとく必要がある。
ここまでは普通。
して、気になる内容はこんな感じ。

DI(依存注入)

依存性のあるデータを外部から指定して注入するとゆー概念。
内部的な依存は調べてない。とりあえず全部放り込んだ。

参照かけるのは、Seasarlog4net でOK
で、元になるコードは以下の通り。

namespace DIContainerTest
{
    public interface ITestHello
    {
        string HelloMessage();
    }

    public class TestHello : ITestHello
    {
        string name;

        public TestHello(string names)
        {
            name = names;
        }

        #region ITestHello メンバ

        public string HelloMessage()
        {
            return "Hello " + name;
        }

        #endregion
    }

    class Program
    {
        ITestHello HelloClass;

        public Program()
        {
            HelloClass = new TestHello("オレオレ");
        }

        public void ShowHello()
        {
            Console.WriteLine(HelloClass.HelloMessage());
        }

        static void Main(string[] args)
        {
            Program program = new Program();
            program.ShowHello();
        }
    }
}

して、このとき「Hello オレオレ」と表示されるわけだが、表示を変えるにはコードを書き換えてコンパイルするしかないわけで、、、また、クラスの差し替えにしてもコンパイルのやり直しが必要になる。

で、結局処理の依存する部分「HelloClass」の中身を外で指定できるようにするのがDI。


マズは、どのインスタンスを取り出すべきなのかを外部ファイルに記述する。(とりあえずSampleInjection.diconというファイル名で保存)

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN" "http://www.seasar.org/dtd/components21.dtd">
<components>
  <component name="hello" class="DIContainerTest.TestHello">
    <arg>"Azalea"</arg>
  </component>

  <component name="ConstructorInjection" class="DIContainerTest.Program" />
</components>

次に、コンストラクタを書き換える。

public Program()
{
    Seasar.Framework.Container.IS2Container container
        = Seasar.Framework.Container.Factory.S2ContainerFactory.Create("SampleInjection.dicon");
    HelloClass = (ITestHello)container.GetComponent("hello");
}

すると、この設定ファイルを書き換えるだけで、作成するインスタンスも初期化引数も変更できると。
内部的には System.Reflection なコードが沢山あるんだろうけど、自分でやるよりは楽ですね。