WindowsForm 画面遷移用属性+コンテナめも(Quill併用)

WindowsFormで画面遷移をする為のカスタム属性のdll。

WindowsFormでの画面遷移は特に決まった方針や指針がないのですが、
管理するクラスをつくらないと、スパゲティのような画面遷移ロジックに
なってしまいます。

内部でQuillを使います。

参照にSeasar.dll、Seasar.Quill.dllを追加。

S2Windowsをベースにカスタマイズした新規DLL。後で見るようにメモ。

ソースをダウンロード

CreateFormAttribute.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace FormManage.Attr
{

    /// <summary>
    /// Windowの表示モードタイプ
    /// </summary>
    public enum FormModalType
    {
        Modal,
        Modeless
    }

    /// <summary>
    /// フォーム生成・表示属性
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class CreateFormAttribute : Attribute
    {
        /// <summary>
        /// 遷移先Formクラス
        /// </summary>
        private readonly Type _type;

        public Type FormType
        {
            get { return _type; }
        }

        /// <summary>
        /// Window表示モードタイプ
        /// </summary>
        private readonly FormModalType _mode = FormModalType.Modeless;

        public FormModalType Mode
        {
            get { return _mode; }
        } 

        /// <summary>
        /// 初期処理メソッド名
        /// </summary>
        private string _initialMethodName;

        public string InitialMethodName
        {
            get { return _initialMethodName; }
            set { _initialMethodName = value; }
        }

        /// <summary>
        /// 返り値用プロパティ名
        /// </summary>
        private string _returnPropertyName = string.Empty;

        public string ReturnPropertyName
        {
            get { return _returnPropertyName; }
            set { _returnPropertyName = value; }
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public CreateFormAttribute(Type type, FormModalType modalType)
        {
            this._type = type;
            this._mode = modalType;
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public CreateFormAttribute(Type type, FormModalType modalType, string initialMethodName)
        {
            this._type = type;
            this._mode = modalType;
            this._initialMethodName = initialMethodName;
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public CreateFormAttribute(Type type, FormModalType modalType, string initialMethodName, string returnPropertyName)
        {
            this._type = type;
            this._mode = modalType;
            this._initialMethodName = initialMethodName;
            this._returnPropertyName = returnPropertyName;
        }

    }
}

FormContainer.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace FormManage.Logics
{
    /// <summary>
    /// フォーム管理用コンテナ
    /// </summary>
    public class FormContainer
    {
        /// <summary>
        /// フォームを保持するDictionary
        /// </summary>
        private static Dictionary<Type,Form> dic = new Dictionary<Type,Form>();

        /// <summary>
        /// フォームを取得する。
        /// なければインスタンス生成。
        /// あればDictionaryから取得。
        /// Disposeされていたら作り直し。
        /// 作ったらDictionaryに追加。
        /// </summary>
        /// <param name="formType"></param>
        /// <returns></returns>
        public static Form GetForm(Type formType)
        {
            Form form;
            bool result = dic.TryGetValue(formType, out form);
            if (result)
            {
                if (form == null || form.IsDisposed)
                {
                    form = (Form)Activator.CreateInstance(formType);
                    dic.Remove(formType);
                    dic.Add(formType,form);
                }
            }
            else
            {
                form = (Form)Activator.CreateInstance(formType);
                dic.Add(formType,form);
            }
            return form;
        }

        /// <summary>
        /// 全てのフォームを閉じる
        /// </summary>
        public static void AllFormClose()
        {
            foreach (Form form in dic.Values)
            {
                if (form != null && !form.IsDisposed)
                {
                    form.Close();
                    form.Dispose();
                }
            }
            dic.Clear();
        }

    }
}

FormInterceptor.cs

using System;
using System.Collections.Generic;
using System.Text;
using Seasar.Framework.Aop;
using Seasar.Framework.Aop.Interceptors;
using System.Windows.Forms;
using System.Reflection;
using Seasar.Quill;
using FormManage.Attr;

namespace FormManage.Logics
{
    /// <summary>
    /// フォーム生成・表示インターセプター
    /// </summary>
    public class FormInterceptor : AbstractInterceptor
    {
        /// <summary>
        /// 返り値用プロパティ名
        /// </summary>
        private string _returnPropertyName = string.Empty;

        /// <summary>
        /// 返り値用プロパティ名
        /// </summary>
        public string Property
        {
            get { return _returnPropertyName; }
            set { _returnPropertyName = value; }
        }
        
        /// <summary>
        /// 指定されたフォームを表示する
        /// </summary>
        /// <param name="invocation"></param>
        /// <returns>DialogResult</returns>
        /// <remarks>
        /// Defaultの戻り値はDialgResult.No。
        /// modal/modelessのフォームを表示する。
        /// CreateFormAttributeに
        /// InitialMethodNameが設定されていれば、表示前にメソッドを実行する。
        /// 戻り値/引数が指定されていれば、受け渡しを行いフォームを表示する。
        /// </remarks>
        public override object Invoke(IMethodInvocation invocation)
        {
            DialogResult retOfReplace = DialogResult.No;

            object ret = retOfReplace;

            // メソッドの引数値の取得
            object[] args = invocation.Arguments;
            ParameterInfo[] pis = invocation.Method.GetParameters();

            IDictionary<string, object> hashOfParams = new Dictionary<string, object>();
            IList<string> listOfParams = new List<string>();
            IDictionary<string, string> hashOfPropNames = new Dictionary<string, string>();

            foreach (ParameterInfo pi in pis)
            {
                hashOfParams.Add(pi.Name.ToLower(), args[pi.Position]);
                listOfParams.Add(pi.Name.ToLower());
            }

            object[] attributes = invocation.Method.GetCustomAttributes(false);
            foreach (object o in attributes)
            {
                if (o is CreateFormAttribute)
                {
                    // 戻り値のプロパティ名を取得する
                    CreateFormAttribute attribute = (CreateFormAttribute)o;
                    Type formType = attribute.FormType;

                    Form form = FormContainer.GetForm(formType);
                    QuillInjector injector = QuillInjector.GetInstance();
                    injector.ClearInjected();
                    injector.Inject(form);
                    // 戻り値プロパティ名の取得
                    string propertyName = String.Empty;
                    if (attribute.ReturnPropertyName != String.Empty)
                        propertyName = attribute.ReturnPropertyName;

                    // フォームに値をセットする
                    PropertyInfo[] infos = form.GetType().GetProperties();
                    foreach (PropertyInfo info in infos)
                    {
                        hashOfPropNames.Add(info.Name.ToLower(), info.Name);
                    }

                    for (int i = 0; i < listOfParams.Count; i++)
                    {
                        if (hashOfPropNames.ContainsKey(listOfParams[i]))
                        {
                            string propName = hashOfPropNames[listOfParams[i]];
                            PropertyInfo property = form.GetType().GetProperty(propName);
                            property.SetValue(form, hashOfParams[listOfParams[i]], null);
                        }
                    }
                    //初期処理メソッド指定あり
                    if (!string.IsNullOrEmpty(attribute.InitialMethodName))
                    {
                        CallMethod(form, attribute.InitialMethodName);
                    }

                    // WindowsFormの表示
                    if (attribute.Mode == FormModalType.Modal)
                    {
                        retOfReplace = form.ShowDialog();
                        ret = retOfReplace;
                        // WindowsFormから戻り値用プロパティから値を取得する
                        if (propertyName != String.Empty)
                        {
                            PropertyInfo propInfo = form.GetType().GetProperty(propertyName);
                            if (propInfo != null)
                                ret = propInfo.GetValue(form, null);
                        }
                    }
                    else
                    {
                        form.Show();
                    }
                }
            }

            return ret;
        }

        /// <summary>
        /// Publicメソッドを実行する
        /// </summary>
        /// <param name="form">対象フォーム</param>
        /// <param name="methodName">Publicメソッド名</param>
        private void CallMethod(Form form,string methodName)
        {
            MethodInfo mi;
            Type mc = form.GetType();
            try
            {
                mi = mc.GetMethod(methodName);
                if (mi != null)
                {
                    mi.Invoke(form, null);
                }
            }
            catch { }
        }
 
    }
}


使う側のインタフェース。

IFormManager.cs

using System;
using System.Collections.Generic;
using System.Text;
using Seasar.Quill.Attrs;
using System.Windows.Forms;
using QuillSample.Dto;
using FormManage.Attr;

namespace QuillSample.Forms
{
    /// <summary>
    /// フォーム遷移管理インタフェース
    /// </summary>
    [Implementation]
    [Aspect(typeof(FormManage.Logics.FormInterceptor))]
    public interface IFormManager
    {
        /// <summary>
        /// メニュー画面を表示する
        /// </summary>
        [CreateForm(typeof(FrmMenu),FormModalType.Modeless)]
        void ShowMenu();

        /// <summary>
        /// 新規作成画面を表示する
        /// </summary>
        [CreateForm(typeof(FrmCreate), FormModalType.Modeless,"Init")]
        void ShowCreate();

        /// <summary>
        /// 新規作成画面に戻る
        /// </summary>
        [CreateForm(typeof(FrmCreate), FormModalType.Modeless)]
        void BackCreate();

        /// <summary>
        /// 確認画面を表示する
        /// </summary>
        /// <param name="empDto">社員情報Dto</param>
        [CreateForm(typeof(FrmConfirmation), FormModalType.Modeless,"Init")]
        void ShowConfirmation(EmpDto empDto);

        /// <summary>
        /// 一覧画面を表示する
        /// </summary>
        [CreateForm(typeof(FrmList), FormModalType.Modeless,"Init")]
        void ShowList();

        /// <summary>
        /// モーダル表示画面を表示する
        /// </summary>
        /// <returns></returns>
        [CreateForm(typeof(FrmModal), FormModalType.Modal)]
        DialogResult ShowModal();

    }
}


起動時のメインフォームはProgram.csにてDictionaryに追加。

    static class Program
    {
        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            QuillInjector injector = QuillInjector.GetInstance();
            FrmMenu form = (FrmMenu)FormContainer.GetForm(typeof(FrmMenu));
            injector.Inject(form);
            Application.Run(form);
        }
    }