かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

S2Windowsの簡単なサンプル

S2WindowSampleと言う名前でWindowsアプリのプロジェクトを作る。
Form1は,とりあえず削除!!

Seasar.NETを使えるようになるまでに

参照設定にlog4netSeasarSeasar.Windowsを追加する。
App.configも追加

ここからはlog4netを使うためのおまじない
AssemblyInfo.csに[assembly: log4net.Config.XmlConfigurator(Watch=true)]を追加する。
ここらへんはドキュメント通り。コピペで済ませよう。


App.config

<configuration>

    <configSections>
        <section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
        <section name="seasar" type="Seasar.Framework.Xml.S2SectionHandler, Seasar" />
    </configSections>
    
    <log4net>
        <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
            <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%-5p %d [%t] %m%n" />
            </layout>
        </appender>

        <root>
            <level value="DEBUG" />
            <appender-ref ref="TraceAppender" />
        </root>

    </log4net>
    
    <seasar>
    </seasar>

</configuration>


log4netの設定読み込みもMainの先頭に書いてしまおう

System.IO.FileInfo info = new System.IO.FileInfo(
   log4net.Util.SystemInfo.AssemblyShortName(
   System.Reflection.Assembly.GetExecutingAssembly())
   + ".exe.config"); // アセンブリがdllの場合は".dll.config"

log4net.Config.XmlConfigurator.Configure(
   log4net.LogManager.GetRepository(), info);


S2Unit.NETや,Seasar.DynamicProxyは今回は使わないので基本設定は終り!


最後に,Seasar.Windows.dllの中身もdiconファイルで使う予定なのでApp.configを下のようにしておく

<configuration>

    <configSections>
        <section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
        <section name="seasar" type="Seasar.Framework.Xml.S2SectionHandler, Seasar" />
    </configSections>

    <log4net>
        <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
            <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%-5p %d [%t] %m%n" />
            </layout>
        </appender>

        <root>
            <level value="DEBUG" />
            <appender-ref ref="TraceAppender" />
        </root>

    </log4net>

    <seasar>
        <configPath>S2WindowsSample.App.dicon</configPath>
        <assemblys>
            <assembly>Seasar.Windows</assembly>
        </assemblys>
    </seasar>

</configuration>


seasarの中にちょびっと追加。
ここらへんはSeasar.NET使ったことあるなら大丈夫なんだろう。
俺はほとんど使ってないから毎回コピペですorz


App.diconファイルも用意して準備完了!

やっとS2Windows・・・

なんだか疲れた。
この一連の作業って地味にめんどくさいですね。
ウィザードとかがそのうち出来る事を祈っておこうかな。

メインウィンドウを出してみよう

ということでメインウィンドウを出します!!
フォームを1つMainFormという名前で追加します。
追加したら,App.diconを*1下のようにする。

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components21.dtd">

<components>
    <component class="Seasar.Windows.S2ApplicationContext">
        <property name="DIContainer">container</property>
        <property name="MainForm">MainForm</property>
    </component>
    
    <component name="MainForm" class="S2WindowsSample.MainForm" />
</components>


ついでにMainも!
さっきのlog4netのコードも入ってこんな感じ。

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Seasar.Framework.Container.Factory;
using Seasar.Framework.Container;

namespace S2WindowsSample
{
    static class Program
    {
        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main()
        {
            System.IO.FileInfo info = new System.IO.FileInfo(
              log4net.Util.SystemInfo.AssemblyShortName(
                System.Reflection.Assembly.GetExecutingAssembly())
                + ".exe.config");

            log4net.Config.XmlConfigurator.Configure(
               log4net.LogManager.GetRepository(), info);

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            SingletonS2ContainerFactory.Init();
            try
            {
                IS2Container con = SingletonS2ContainerFactory.Container;
                ApplicationContext ctx = (ApplicationContext)con.GetComponent(typeof(ApplicationContext));
                Application.Run(ctx);
            }
            finally
            {
                SingletonS2ContainerFactory.Destroy();
            }
        }
    }
}


これで実行するとウィンドウが出ます。*2
Mainの中の書き方は,どこにも見当たらなかったけどこれで動いてるからよしとしよう。


次は,ボタンを押したらウィンドウが表示されるようにしましょう。
Dispacherというフォルダをプロジェクト内に作って,そこにIFormDispacherというインターフェイスを追加します。
ここでは,Showなにがしという名前のメソッドをフォームを表示するときのメソッドとして使います。
ということで,App.diconにIFormDispacherを登録しませふ。
IFormDispacherにはFormInterceptorをアスペクトに指定します。


これでApp.diconはこんな感じになりました。

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components21.dtd">

<components>
    <component class="Seasar.Windows.S2ApplicationContext">
        <property name="DIContainer">container</property>
        <property name="MainForm">MainForm</property>
    </component>

    <component class="S2WindowsSample.Dispacher.IFormDispacher">
        <aspect pointcut="^Show.*$">
            <component class="Seasar.Windows.AOP.Interceptors.FormInterceptor" />
        </aspect>
    </component>
    
    <component name="MainForm" class="S2WindowsSample.MainForm" />
</components>


下地は出来た!(はず)
Formをもう1個作ろう。
HelloFormという名前のフォームを作って,App.diconに登録する。
HelloFormはボタンが押される度に何個も出てきて欲しいのでprototypeにしておきます。


そして,IFormDispacherにメソッド追加。
TargetForm属性で,どのフォームをどういう風に表示するかきめるみたい。
メソッド名はdiconファイルに登録した正規表現にマッチするように注意だ!

==IFormDispacher.cs------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Seasar.Windows.Attr;

namespace S2WindowsSample.Dispacher
{
    public interface IFormDispacher
    {
        [TargetForm(typeof(HelloForm), ModalType.Modaless)]
        void ShowHelloForm();
    }
}


MainFormにIFormDispacher型のプロパティを追加します。
Dispacherって名前でいいかな。
追加したらボタンを1つ置いてクリックイベントハンドラで下のように書きます。

==MainForm.cs------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using S2WindowsSample.Dispacher;

namespace S2WindowsSample
{
    public partial class MainForm : Form
    {
        private IFormDispacher dispacher;

        public IFormDispacher Dispacher
        {
            get { return dispacher; }
            set { dispacher = value; }
        }

        public MainForm()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.Dispacher.ShowHelloForm();
        }
    }
}


これで実行してみると…。
ボタンを押すとフォームがでます!調子にのって押しまくるといっぱいになります。

パラメータを渡す

最後に,HelloFormにパラメータを渡す方法をやります。
HelloFormにラベルを1つ追加します。
HelloFormにMessageというプロパティを用意してsetに先程のラベルのテキストにvalueを設定するように書きませふ。


IFormDispacherのShowHelloFormに引数を1つ追加します。
引数名と型は,先程ついかしたMessageプロパティの名前とあわせます。

こんな感じです

==IFormDispacher.cs----------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Seasar.Windows.Attr;

namespace S2WindowsSample.Dispacher
{
    public interface IFormDispacher
    {
        [TargetForm(typeof(HelloForm), ModalType.Modaless)]
        void ShowHelloForm(string Message);
    }
}


MainFormでコンパイルエラーが出るようになるので,引数に適当な値を渡してやるように変更しませふ。
後は,コンパイル実行!!!
ボタンを押すと,メッセージが設定されたフォームがポコポコ出てきます。
値をちゃんと渡せてそうです。
DTOとか渡すようになるのかな?


さて,ちなみに今のIFormDispacherのメソッドの戻り値はvoidですが,DialogResultにすることも出来ます。
ただし,モーダレスの場合は,常にNoが返るはず。
モーダルのときだけ使えますな。

ここらへんこの先どうなるか楽しみです。

*1:本当は,App.diconじゃなくて他のdiconファイルを作ってそこに書くのが理想的だけどサンプルだしめんどくさくなって…

*2:当然App.diconは埋め込まれたリソースに!!俺は最初忘れてたorz