无法实现具有约束的多通用参数方法?

时间:2012-09-03 16:09:59

标签: c# generics interface constraints

我有以下接口声明:

public interface IBasePresenter
{
    void Run();
    void ShowDialog<T, M>(T t, M m ) where T : UserControl where M : Form,      ISomeInterface<SomeType>;
}

ShowDialog()基本上是一种向用户显示模态对话框的方法。在哪里&#39; T&#39;是父表单,M是要显示的唯一对话框。 M有多种不同的类型!因此选择通用方法的原因!

我认为可以使用这种方法的几种方法:

Presenter.ShowDialog(this, typeof(Form1)); // FigA

或者

Presenter.ShowDialog(this, new Form1()); // FigB

基于图A或B,示例ShowDialog()方法实现到底是什么样的?

我的问题源于试图弄清楚通用参数&#39; M&#39;在ShowDialog()方法实现中实例化。

4 个答案:

答案 0 :(得分:5)

猜测:

m.Controls.Add(t);
m.ShowDialog();

但是,坦率地说,我不确定这个实用程序方法是否会增加很多用处,而且它也可能是非泛型的(void ShowDialog(Control t, Form m))。如果使用: new()约束,它可能会更有用,这也可以避免在多个表单上使用相同控件实例的风险(非法)。但正如我所说的那样:坦率地说,我不会理会这种方法,直到它证明了一些非平凡的用处。如果我确实保留了它,我会将参数重命名为更有启发性;没有M,m,T,t告诉我他们的意思。

答案 1 :(得分:4)

您无法使用Fig A方式,因为typeof(Form1)System.Type,而不是Form;除非存在带有System.Type类型的第二个参数的重载,否则代码将无法编译。

  

如何在ShowDialog()方法实现中实例化泛型参数“M”?

它不是“实例化”它是“推断:”您已经提供了实例;编译器从调用中推断出类型。

答案 2 :(得分:2)

您可以按如下方式更改通用方法签名:

public void ShowDialog<T>() where T : Form, new() {
    using(var dialog = new T()){
        dialog.ShowDialog();
    }
}

然后是电话:

ShowDialog<MyCoolDialog>();

会导致mtheod创建(不会推断此时间;))表单的新实例并以模态方式显示。

答案 3 :(得分:0)

以下是界面方法的稍微更新版本

    void ShowDialog<TParentForm, TDialogForm, TModel, TEntity>(TParentForm t, TDialogForm m, Action callback)
        where TParentForm : UserControl
        where TModel : class, IModel<TEntity>, new()
        where TDialogForm : Form, IEditableItem<TEntity>, new();

我对之前的版本做了一些假设,因此在我的测试和细化阶段,方法签名已经改变。它对我来说仍然是一个或多或少的教育练习所以我仍然想知道如何实现它而不是简单的选择简单的出路。

该方法的示例实施

    public void ShowDialog<TParentForm, TDialogForm, TModel, TEntity>(TParentForm t, TDialogForm m, Action callback)
        where TParentForm : UserControl
        where TModel : class, IModel<TEntity>, new()
        where TDialogForm : Form, IEditableItem<TEntity>, new()
    {
        using (var dialogToShow = new TDialogForm())
        {
            dialogToShow.StartPosition = FormStartPosition.CenterScreen;
            dialogToShow.FormBorderStyle = FormBorderStyle.FixedSingle;
            dialogToShow.Model = new TModel();

            // 2. show the new user control/form to the user.
            var result = dialogToShow.ShowDialog(t);

            // 3. handle the dialog result returned and update the UI appropriately.
            if (result == DialogResult.OK)
            {
                // print status label.
                callback.Invoke();
            }
        }
    }

我不完全确定为什么&#39; TDialogForm m&#39;参数仍在那里,因为它似乎没有在任何地方使用。

如何使用方法:

    private void BtnAddNewServiceClick(object sender, EventArgs e)
    {            
        Presenter.ShowDialog<ServerRolesControl, AddNewServiceForm, ServiceModel, Role>(this, new AddNewServiceForm(), SetAddedRolesLabel);
    }

    private void BtnViewAllServicesClick(object sender, EventArgs e)
    {
        Presenter.ShowDialog<ServerRolesControl, ViewRolesForm, ServiceModel, Role>(this, new ViewRolesForm(), SetDeletedRolesLabel);
    }

我应该更新界面方法但是让它工作真是太痛苦我宁愿现在单独离开=)。