3

I have the following Interface Declaration:

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

The ShowDialog() is basically a method that will show a modal dialog box to the user. Where 'T' is the parent Form and M is the unique dialog to show. M of which there are multiple different types! Hence the reason to choose a generic method!

A couple of ways I think this method could be used:

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

Or

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

Based upon Fig A or B, what exactly will a sample ShowDialog() method implementation look like?

My questions stems from trying to figure how the generic parameter 'M' is instantiated inside of a ShowDialog() method implementation.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
IbrarMumtaz
  • 4,235
  • 7
  • 44
  • 63
  • It's not really clear what your question is. You've said what it "stems from" but you haven't really asked a question... or explained what you mean even in the "stems from" question. – Jon Skeet Sep 03 '12 at 16:13
  • @IbrarMumtaz: No, specifying c#-4.0 doesn't specify which framework version you're using. You could be targeting .NET 2.0. – Jon Skeet Sep 03 '12 at 16:14
  • @IbrarMumtaz: Also C# has 32K followers vs 1.7K of C#-4.0. You'll be much more likely to get views. – Tudor Sep 03 '12 at 16:15

4 Answers4

5

At a guess:

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

However, frankly I'm not sure this utility method adds much useful, and it could just as well be non-generic (void ShowDialog(Control t, Form m)). It could perhaps be more useful if using the : new() constraint, which would also avoid the risk of using the same control instance on multiple forms (illegal). But as I say: frankly I wouldn't bother with this method until it had demonstrated some non-trivial usefulness. And if I did keep it, I'd rename the parameters to be more illuminating; none of M, m, T, t tell me what they mean.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 3
    +1 I agree with the point about generics not making much sense here. – Tudor Sep 03 '12 at 16:16
  • actually making it non generic makes sense here so ty! – IbrarMumtaz Sep 03 '12 at 16:18
  • @IbrarMumtaz btw, forgot to say - but FigB makes more sense here, *except* for the fact that it will never get disposed. You might want to add a `using(m) {...}` around everything. – Marc Gravell Sep 03 '12 at 16:22
  • Yeah. Unless something specific to a derived Control or Form has to be done, the assignement compatibility of derived types alone solves the problem and generics are completely superfluous. – Olivier Jacot-Descombes Sep 03 '12 at 16:26
4

You cannot use the Fig A way because typeof(Form1) is a System.Type, not a Form; the code will not compile unless there is an overload that takes a second parameter of type System.Type.

how the generic parameter 'M' is instantiated inside of a ShowDialog() method implementation?

It is not "instantiated" it is "inferred:. You provided the instance already; the compiler infers the type from the invocation.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

You could change the generic method signature as follows:

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

and then the call:

ShowDialog<MyCoolDialog>();

would result in the mtheod creating (not inferring this time ;)) a new instance of the form and showing it in a modal way.

Spontifixus
  • 6,570
  • 9
  • 45
  • 63
  • 2
    Note: if doing this, adding a `using` to the new form would be a good idea, otherwise the form won't be disposed. Of course, that might then mean that removing the control "t" would be a good idea too. – Marc Gravell Sep 03 '12 at 16:34
  • Thanks for this, this is pretty much the nudge in the right direction I needed. I will post up my answers tomorrow to show what the 'ShowDialog()' now looks like and how I used it. Hopefully it can educate some others ppl in a similar situation. – IbrarMumtaz Sep 05 '12 at 16:32
0

Below is an slightly updated version of the interface method:

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

I made some assumptions on the previous version so during my testing and refinement phase the method signature has changed. It's still more or a less a en educational exercise for me so I still wanted to know how to pull it off rather than simple chose the easy way out.

A sample implementation of the method:

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

I am not entirely sure why the 'TDialogForm m' parameter is still in there as it does not seem to be used anywhere.

How to use the method:

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

I should update the interface method but it was so much pain getting it to work I would rather leave it alone now =).

IbrarMumtaz
  • 4,235
  • 7
  • 44
  • 63