3 votes

Impossible d'implémenter une méthode basée sur plusieurs paramètres génériques avec des contraintes ?

J'ai la déclaration d'interface suivante :

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

La méthode ShowDialog() permet d'afficher une boîte de dialogue modale à l'utilisateur. Où 'T' est le formulaire parent et M est la boîte de dialogue unique à afficher. M dont il existe plusieurs types différents ! D'où la raison de choisir une méthode générique !

Je pense que cette méthode pourrait être utilisée de plusieurs façons :

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

Ou

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

Sur la base de la figure A ou B, à quoi ressemblera exactement un exemple d'implémentation de la méthode ShowDialog() ?

Je me demande comment le paramètre générique "M" est instancié dans l'implémentation de la méthode ShowDialog().

5voto

Marc Gravell Points 482669

A vue de nez :

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

Cependant, franchement, je ne suis pas sûr que cette méthode utilitaire ajoute beaucoup d'utilité, et elle pourrait tout aussi bien être non générique ( void ShowDialog(Control t, Form m) ). Il serait peut-être plus utile d'utiliser l'option : new() ce qui éviterait également le risque d'utiliser la même instance de contrôle sur plusieurs formulaires (illégal). Mais comme je l'ai dit : franchement, je ne m'embêterais pas avec cette méthode tant qu'elle n'aurait pas démontré une utilité non triviale. Et si je la gardais, je renommerais les paramètres pour qu'ils soient plus éclairants ; aucun des M, m, T, t ne me dit ce qu'ils signifient.

4voto

dasblinkenlight Points 264350

Vous ne pouvez pas utiliser le Fig A parce que typeof(Form1) est un System.Type et non un Form le code ne compilera pas à moins qu'il n'y ait une surcharge qui prenne un second paramètre de type System.Type .

comment le paramètre générique "M" est instancié dans l'implémentation d'une méthode ShowDialog() ?

Il n'est pas "instancié", il est "inféré". Vous avez déjà fourni l'instance ; le compilateur déduit le type de l'invocation.

2voto

Spontifixus Points 5272

Vous pourriez modifier la signature de la méthode générique comme suit :

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

et ensuite l'appel :

ShowDialog<MyCoolDialog>();

aurait pour effet de créer (et non de déduire cette fois-ci ;)) une nouvelle instance du formulaire et de l'afficher de manière modale.

0voto

IbrarMumtaz Points 1223

Voici un exemple version actualisée de la méthode de l'interface :

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

J'ai fait quelques suppositions sur la version précédente, donc pendant ma phase de test et de raffinement, la signature de la méthode a changé. Il s'agit toujours plus ou moins d'un exercice éducatif pour moi, je voulais donc savoir comment le réaliser plutôt que de choisir la solution de facilité.

Un échantillon mise en œuvre de la méthode :

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

Je ne suis pas tout à fait sûr de la raison pour laquelle le paramètre 'TDialogForm m' est toujours là, puisqu'il ne semble pas être utilisé ailleurs.

Comment utiliser la méthode :

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

Je devrais mettre à jour la méthode de l'interface mais j'ai eu tellement de mal à la faire fonctionner que je préfère la laisser tranquille maintenant =).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X