2010-10-16 13 views
67

Necesito tener algunos delegados en mi clase.Cómo agregar un delegado a una interfaz C#

Me gustaría usar la interfaz para "recordarme" que establezca estos delegados.

Cómo?

Mi mirada clase como esta:

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

necesito una interfaz para obligar a los delegados:

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

Respuesta

115

Aquellos están declarando delegado tipos. No pertenecen a una interfaz. Los eventos utilizando los tipos de delegados están muy bien estar en la interfaz sin embargo:

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

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

no (y no debe) redeclare el tipo de delegado, más de lo que sería redeclare cualquier otro tipo que se utiliza la aplicación en una interfaz.

+0

Esto simplemente no está funcionando para mí. Estoy seguro de que hice todo de esta manera y, sin embargo, mi controlador dentro de mi interfaz no está siendo reconocido. Mi clase que implementa la interfaz se queja de que la clase no coincide con el tipo de retorno de interfaz de System.EventHandler. – Chucky

+1

@Chucky: Parece que debes hacer una nueva pregunta con un ejemplo breve pero completo que demuestre el problema. La respuesta que he dado realmente * funciona *. –

+4

No me di cuenta de que los delegados tienen el mismo nivel de accesibilidad que las clases. Siempre pensé que debían ser encapsulados dentro de una clase. – Purusartha

6

La respuesta de Jon Skeet es correcta, solo quiero agregar una nota.

Las interfaces no están ahí para "recordarle" qué hacer o qué incluir en sus clases. Las interfaces son medios de abstracción, utilizados en programación orientada a objetos y métodos de diseño. Tal vez no necesite una declaración de interfaz en absoluto, a menos que desee ver algunas instancias de clase concretas como la interfaz en otro lugar de su programa (Abstracción).

Si desea aplicar algunos estándares de codificación en su proyecto, puede intentar usar herramientas de análisis de código (como en Visual Studio) - Permiten extensiones, que puede incorporar para agregar sus propias reglas de análisis de código.

Usando el análisis de código, si "olvida" agregar los delegados (aunque no veo el punto de olvidarlo, como si el delegado no se utilizara, no es necesario) recibirá una advertencia/error .

+1

Puede que tengas razón, pero algunas veces haces algunas suposiciones que incluso con una buena documentación es difícil de recordar después de un tiempo. Intento reutilizar mi código, pero a veces no puedo recordar qué es el núcleo y qué no (cuando se trata de delegados, es difícil para mí ver el panorama completo) – Asaf

23

Desde .NET 3.5 también puede utilizar los delegados System.Action, lo que resultaría en la siguiente interfaz:

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

    public event Action Started; 
} 
+0

+1. Considero que Action/Func es mucho más elegante (y legible) que los tipos de delegados tradicionales _y_ puede definirlos en su interfaz. – chrnola

0

La interfaz heredada dentro de su clase derivada le recordará que debe definir y vincular la materia usted declaró en eso.

Pero es posible que también desee utilizarlo explícitamente y aún deberá asociarlo a un objeto.

Por ejemplo, usando un patrón de Inversión de Control:

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

Usted puede intentar algo como esto.

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

Uno de sus comentarios hace referencia al tipo de devolución del controlador de eventos. ¿Le preocupa más el tipo de controlador o los datos que regresan del evento? Si es el último, entonces esto puede ayudar. De lo contrario, esta solución no será suficiente, pero puede ayudarlo a estar más cerca de lo que está buscando.

Todo lo que tiene que hacer es declarar a sus controladores de eventos como controladores genéricos de eventos tanto en la interfaz como en su implementación y puede personalizar los resultados de devolución.

Su clase conrete se vería así:

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

Su interfaz se vería así:

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

Ahora que los argumentos del evento están regresando a sus tipos, se puede conectar en cualquier manejador tú defines

Como referencia: https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx

3

Sólo exponga el delegado como una propiedad

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

public interface IMyInterface 
{  
    UpdateStatusEventHandler StatusUpdated {get; set;}  
    StartedEventHandler Started {get; set;} 
} 
Cuestiones relacionadas