2010-10-16 7 views
67

Je dois avoir des délégués dans ma classe. Je voudrais utiliser l'interface pour me "rappeler" de définir ces délégués.Comment ajouter un délégué à une interface C#

Comment?

Mon look classe comme ceci:

public class ClsPictures : myInterface 
{ 
    // Implementing the IProcess interface 
    public event UpdateStatusEventHandler UpdateStatusText; 
    public delegate void UpdateStatusEventHandler(string Status); 

    public event StartedEventHandler Started; 
    public delegate void StartedEventHandler(); 
} 

j'ai besoin d'une interface pour forcer les délégués:

public interface myInterface 
{ 
    // ????? 
} 

Répondre

115

Les proclamons délégué types. Ils n'appartiennent pas à une interface. Les événements utilisant ces types de délégués sont très bien d'être dans l'interface bien:

public delegate void UpdateStatusEventHandler(string status); 
public delegate void StartedEventHandler(); 

public interface IMyInterface 
{  
    event UpdateStatusEventHandler StatusUpdated;  
    event StartedEventHandler Started; 
} 

La mise en œuvre ne sera pas (et ne devrait pas) redéclarer le type de délégué, pas plus qu'il ne serait redéclarer tout autre type utilisé dans une interface.

+0

Ce ne fonctionne tout simplement pour moi. Je suis certain que j'ai tout fait de cette façon, et pourtant, mon gestionnaire dans mon interface n'est pas reconnu. Ma classe qui implémente l'interface se plaint que la classe ne correspond pas au type de retour d'interface de System.EventHandler. – Chucky

+1

@Chucky: On dirait que vous devriez poser une nouvelle question avec un exemple court mais complet illustrant le problème. La réponse que j'ai donnée fonctionne vraiment. –

+4

Je n'avais pas réalisé que les délégués avaient le même niveau d'accessibilité que les cours. J'ai toujours pensé qu'ils devaient être encapsulés dans une classe. – Purusartha

6

La réponse de Jon Skeet est juste, je veux juste ajouter une note.

Les interfaces ne sont pas là pour vous «rappeler» quoi faire ou quoi inclure dans vos cours. Les interfaces sont des moyens d'abstraction, utilisés dans la programmation orientée objet et les méthodes de conception. Peut-être n'avez-vous pas du tout besoin d'une déclaration d'interface, à moins que vous ne souhaitiez voir des instances de classes concrètes en tant qu'interface ailleurs dans votre programme (Abstraction). Si vous souhaitez imposer des normes de codage dans votre projet, vous pouvez essayer d'utiliser des outils d'analyse de code (comme dans Visual Studio) - Ils permettent des extensions que vous pouvez incorporer pour ajouter vos propres règles d'analyse de code. En utilisant l'analyse de code, si vous "oubliez" d'ajouter les délégués (bien que je ne vois pas l'intérêt de l'oublier, comme si le délégué n'était pas utilisé, ce n'est pas nécessaire) vous obtiendrez un avertissement/erreur .

+1

Vous avez peut-être raison, mais il y a des moments où vous faites des suppositions qu'avec une bonne documentation. c'est difficile de se souvenir après un moment. J'essaie de réutiliser mon code mais parfois je ne me souviens plus de ce qu'est le noyau et de ce qu'il n'est pas (quand il s'agit de délégués - c'est difficile pour moi de voir la grande image ...) – Asaf

23

Depuis .NET 3.5, vous pouvez également utiliser les délégués System.Action, qui conduiraient à l'interface suivante:

public class ClsPictures : myInterface 
{  
    // Implementing the IProcess interface 
    public event Action<String> UpdateStatusText; 

    public event Action Started; 
} 
+0

+1. Je trouve Action/Func beaucoup plus élégant (et lisible) que les types de délégués traditionnels _et_ vous pouvez les définir dans votre interface. – chrnola

0

L'interface héritée de votre classe dérivée vous rappellera pour définir et relier les choses vous avez déclaré dedans.

Mais vous pouvez également vouloir l'utiliser explicitement et vous devrez toujours l'associer à un objet.

Par exemple en utilisant un modèle de contrôle d'inversion:

class Form1 : Form, IForm { 
    public Form1() { 
    Controls.Add(new Foo(this)); 
    } 

    // Required to be defined here. 
    void IForm.Button_OnClick(object sender, EventArgs e) { 
    ... 
    // Cast qualifier expression to 'IForm' assuming you added a property for StatusBar. 
    //((IForm) this).StatusBar.Text = $"Button clicked: ({e.RowIndex}, {e.SubItem}, {e.Model})"; 
    } 
} 

Vous pouvez essayer quelque chose comme ça.

interface IForm { 
    void Button_OnClick(object sender, EventArgs e); 
} 


class Foo : UserControl { 
    private Button btn = new Button(); 

    public Foo(IForm ctx) { 
    btn.Name = "MyButton"; 
    btn.ButtonClick += ctx.Button_OnClick; 
    Controls.Add(btn); 
    } 
} 
1

Un de vos commentaires faisait référence au type de retour du gestionnaire d'événements. Êtes-vous plus concerné par le type de gestionnaire, ou les données qui reviennent de l'événement? Si c'est le dernier, cela peut aider. Si ce n'est pas le cas, cette solution ne suffira pas, mais pourrait vous aider à vous rapprocher de ce que vous recherchez.Tout ce que vous avez à faire est de déclarer vos gestionnaires d'événements en tant que gestionnaires d'événements génériques dans l'interface et votre implémentation et vous pouvez personnaliser les résultats de retour.

Votre classe conrete ressemblerait à ceci:

public class ClsPictures : myInterface 
{ 
    // Implementing the IProcess interface 
    public event EventHandler<UpdateStatusEventArgs> UpdateStatusText; 
    //no need for this anymore: public delegate void UpdateStatusEventHandler(string Status); 

    public event EventHandler<StartedEventArgs> Started; 
    //no need for this anymore: public delegate void StartedEventHandler(); 
} 

Votre Interface ressemblerait à ceci:

public interface myInterface 
{ 
    event EventHandler<StartedEventArgs> Started; 
    event EventHandler<UpdateStatusEventArgs> UpdateStatusText; 
} 

Maintenant que les args d'événements reviennent vos types, vous pouvez les accrocher dans un gestionnaire vous définissez.

Pour référence: https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx

3

Juste exposer le délégué en tant que propriété

public delegate void UpdateStatusEventHandler(string status); 
public delegate void StartedEventHandler(); 

public interface IMyInterface 
{  
    UpdateStatusEventHandler StatusUpdated {get; set;}  
    StartedEventHandler Started {get; set;} 
} 
Questions connexes