0

そこで、WinFormsを使用してC#でMDIアプリケーションを構築しています。このシナリオでDRYをフォローする方法を一生理解することはできません。メインメニューストリップのtoolstripmenuitemsを使用して、新しいMDIの子を開きます。これらのそれぞれのイベントハンドラーとして「NewChild」メソッドを再利用しました。すべての子ウィンドウがインスタンス化のために同じパターンに従うため、子ウィンドウごとに繰り返す必要がないようにしています。

ジェネリックスを調べてTypeクラスを使用しましたが、実際には目的の場所に到達しません。理想的には私はただ言いたいです

    // etc...
    TypeOfForm = ConfigurationForm;
}

new TypeOfForm();

しかし、私はそのような失われた言語構造が存在するとは思わない。

public partial class MainForm : Form
{
    private AboutForm aboutForm;
    private ConfigurationForm configForm;
    private ResultsForm resultForm;
    private LogForm logForm;

    private void NewChild(object sender, EventArgs e)
    {
        Form newForm;

        if (sender == testConfigurationToolStripMenuItem)
        {
            if (configForm == null)
            {
                configForm = new ConfigurationForm();
            }
            newForm = configForm;
        }
        else if (sender == resultsToolStripMenuItem)
        {
            if (resultForm == null)
            {
                resultForm = new ResultsForm();
            }
            newForm = resultForm;
        }
        else if (sender == logToolStripMenuItem)
        {
            if (logForm == null)
            {
                logForm = new LogForm();
            }
            newForm = logForm;
        }
        else
        {
            return;
        }

        newForm.MdiParent = this;
        newForm.Disposed += new EventHandler(ChildDisposed);
        newForm.Show();
    }
}

このような状況でDRYを実装するための良い方法は何でしょうか?

4

2 に答える 2

1

私は絶対にタイプをチェックすることを避けます。それは本当にコードを乱雑にします。

あなたは本当にこの一般的なコードにジェネリックスを使いたいです:

// for multiple instance forms (and instantiating a "singleton" form)
private void AddNewChild<T>() where T: Form
{
    T newForm = new T();
    newForm.MdiParent = this;
    newForm.Disposed += new EventHandler(ChildDisposed);
    newForm.Show();   
}

// for "singleton" forms
private void ActivateChild<T>() where T: Form
{
    // off-the-cuff guess, this line may not work/compile
    var child = this.MdiChildren.OfType<T>().FirstOrDefault();

    if (child == null) 
    {
        AddNewChild<T>();
    }
    else
    {
        child.Show();
    }
}

// usage
logToolStripMenuItem.Click += (s,e) => ActivateChild<LogForm>();
testConfigurationToolStripMenuItem.Click += (s,e) => ActivateChild<ConfigurationForm>();
multipleInstanceFormMenuItem.Click += (s,e) => AddNewChild<FormX>();
...
于 2013-03-26T17:48:54.317 に答える
0

ここに1つの提案があります:

ツールストリップオブジェクト(またはTagプロパティを使用)とそれに対応するフォームまたはフォームタイプを使用して辞書を作成します

// you can't use the UI controls before Init, you could use their Tags
// so this should be considered pseudo code
private Dictionary<string, Type> ToolstripForms = new Dictionary<string, Type>
{
    { testConfigurationToolStripMenuItem, typeof(ConfigurationForm) }, 
    { resultsToolStripMenuItem, typeof(ResultsForm) }, 
};

NewFormメソッドで:

private void NewChild(object sender, EventArgs e)
{
    Form newForm = null;

    // some casting and exception handling would go well here
    if (sender != null && ToolstripForms.ContainsKey(sender)) // or sender.Tag?
    {
        newForm = Activator.CreateInstance(ToolstripForms[sender]) as Form;
    }
    ...
}

フォームがすでに開いているかどうかを判断し、毎回新しいフォームを開くのではなく、それに焦点を合わせる方法が必要になる場合がありますが、それはあなた次第です。1つのアプローチは、そのディクショナリの値としてオブジェクトのペア(タイプと既存のインスタンス)を使用することですが、他のアプローチの方がおそらく見栄えがよいでしょう。

于 2013-03-26T18:04:06.273 に答える