これから始めるSpring.NET その3

それでは実際にSpring.NET を使ってみます。

まずは以下のサイトから最新のバイナリをダウンロードしてきます。現在のバージョンは1.1 です。
Spring.NET - Application Framework

ダウンロードしたSpring.NET-1.1.zip を解凍するとできるフォルダの中の「bin\net\2.0\release」フォルダにあるファイルから以下のファイルを適当な場所にコピーしておきます。

  • Spring.Core.dll
  • antlr.runtime.dll
  • Common.Logging.dll

プロジェクトの作成

開発環境にはVisual C# 2008 Express Edition を使用します。

プロジェクトの種類を「Windows フォーム アプリケーション」にして、「SpringSample」というプロジェクト名で新規作成します。
まずは先程コピーしたSpring.Core.dll を参照設定に追加して下さい。
プロジェクトに初めから追加されているForm1クラスのクラス名を「MainForm」に変更します。とりあえず、このフォームをDI コンテナに登録して取り出し、表示してみます。

プロジェクトに「objects.config」というファイル名でXMLファイルを追加します。このファイルをオブジェクト定義ファイルと呼びます。ルート要素として、「objects」というタグを追加し、名前空間を「http://www.springframework.net」と宣言しておきます。

objects.config
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">
</objects>

では、オブジェクト定義ファイルにフォームの定義を追加してみましょう。

定義を追加するには「object」というタグを使います。色々な属性が用意されていますが、ここでは以下の属性を指定します。

name属性
オブジェクト名を指定します。これはオブジェクトの識別子で一意にする必要があります。
type属性
型名(型名, アセンブリ名というフォーマット)を指定します。
objects.config
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net">
    <object name="mainForm" type="SpringSample.MainForm, SpringSample" />
</objects>

これは意味的には以下のC#のコードと等価と考えてください。

MainForm mainForm = new MainForm();

それではDI コンテナからこのフォームを取り出し、表示してみましょう。

まず、「objects.config」を出力ディレクトリにコピーするように設定しておきます(プロパティから設定します)。
そして、エントリーポイントのある「Program」クラスに以下のコードを追加します。

Program.cs
using System;
using System.Windows.Forms;

using Spring.Context;
using Spring.Context.Support;

namespace SpringSample {
    static class Program {
        [STAThread]
        static void Main() {
            IApplicationContext context = new XmlApplicationContext("objects.config");

            Application.Run((Form)context.GetObject("mainForm"));
        }
    }
}
  1. Spring.Context.Support.XmlApplicationContext クラスにオブジェクト定義ファイルの場所を指定して、インスタンス化します。この時、変数の型はIApplicationContext 型にしておきます。
  2. そして、IApplicationContext のGetObjectメソッドでフォームのインスタンスを取得します。この時、引数にはオブジェクト名(objectタグのname属性で指定したあれです)を指定します。
  3. あとはApplication::Run でアプリケーションを開始します。

これでフォームを表示することができました。

アプリケーションコンテキスト

では、詳しく見ていきます。

IApplicationContext context = new XmlApplicationContext("objects.config");

これはアプリケーションコンテキストと呼ばれるもの初期化しています。アプリケーションコンテキストはオブジェクト定義ファイルで宣言されたオブジェクトを取り出すためのエントリーポイントになります。
アプリケーションコンテキストには何種類かあり、ここではオブジェクト定義ファイルの場所を直接指定して取得しています。

では、アプリケーションコンテキストでは実際に何が行われているのでしょうか?それは大きく分けて次のようになります。

  1. オブジェクト定義ファイルを読み込む(パースする)。
  2. objectタグで指定された型を解決する(その型が存在しなければその時点で例外が出る)。
  3. singleton=true且つ、lazy-init=false で宣言された型をインスタンス化する(プールしておく)。

最後のsingleton とlazy-init というのは、objectタグで定義できる属性のことを指します。これらの属性はそれぞれ次のような意味を持ちます。

属性 意味 規定値
singleton Singletonオブジェクトかどうか true
lazy-init 遅延生成かどうか false

Singletonオブジェクトとは、そのクラスのインスタンスが一つしか作られないということを意味します。これはGoFデザインパターンに由来しています。
遅延生成はアプリケーションコンテキストにオブジェクトが要求された時に初めてインスタンス化するということです。

これらの属性を指定しなければそれぞれの規定値に従うので、ここではアプリケーションコンテキストを初期化した時点で、MainFormクラスのインスタンスが生成されることになります。
もちろん、これでは初期化時のオーバーヘッドが高すぎるので、通常はlazy-initをtrue にしておくことをお勧めします。

あとはGetObjectメソッドでオブジェクト名を指定されると、そのオブジェクト名で定義されたオブジェクトのインスタンスを返します(そのオブジェクトが存在しないと例外が投げられます)。
オブジェクトはオブジェクト名で取得する他にも、型を指定して取得する事もできます。

ここでやっている事は、以下のコードと等価になります。

Program.cs
using System;
using System.Windows.Forms;

namespace SpringSample {
    static class Program {
        [STAThread]
        static void Main() {
            Form mainForm = new MainForm();

            Application.Run(mainForm);
        }
    }
}

では、もう少し意味のあることをしてみます。オブジェクト定義ファイルを以下のように変更して下さい。

objects.config
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net">
    <object name="mainForm" type="SpringSample.MainForm, SpringSample" lazy-init="true">
        <property name="Text" value="Hello" />
        <property name="StartPosition" value="CenterScreen" />
        <property name="Size" value="250, 250" />
        <property name="BackColor" value="Blue" />
    </object>
</objects>

propertyタグでプロパティの値を設定することができます。それぞれの属性の意味は以下になります。

name属性
プロパティ名を指定しします。
value属性
プロパティに設定する値を指定します。

value属性で指定した値は、プロパティの型が変換できる型であれば自動的に変換されます。

  • CenterScreen → System.Windows.Forms.FormStartPosition.CenterScreen
  • 250, 250 → System.Drawing.Size
  • Blue → System.Drawing.Color.Blue

この機能は何も特別なものではなく、.NET標準のTypeConverterを使って実装されています。