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); } }