2012-02-16 6 views
22

¿Está mal modificar EventArgs en controladores de eventos con el fin de pasar información a la clase que invoca el evento?Uso de EventArgs para pasar información a la clase invocadora

Por ejemplo, si tengo una clase de comunicación de bajo nivel que necesita validar un certificado para SSL pero no tiene forma de saber cómo es un certificado válido ya que es el conocimiento de los diferentes usuarios de la clase.

class ValidationEventArgs : System.EventArgs 
{ 
    public X509Certificate Certificate { get; set; } 
    public bool Valid { get; set; } 
} 

Luego, en los que utilizan objetos que conectar con el evento, y comprobar que de alguna manera cambiar la bandera Valid para indicar si el certificado es aceptable o no.

comms.ValidationEvent += CertValidationHandler; 

void CertValidationHandler(ValidationEventArgs args) 
{ 
    if (args.Certificate.Issuer.Contains(COMPANY_NAME) 
     args.Valid = true; 
} 

he encontrado references de EventArgs siendo utilizados como este, pero también he visto a la gente diciendo que no es recomendable.

Editar: Tal vez debería aclarar que no se trata de heredar EventArgs, sino de usarlos como un canal de comunicación bidireccional. Como otros comentaron, esto es aceptable y cualquier ruido que Google elija es probablemente solo que la gente haya malinterpretado o utilizado mal el concepto y ahora tiene la misma cruzada personal contra goto.

+6

¿Quién dice que no es recomendable? Esto sucede todo el tiempo en el marco. Mire ['CancelEventArgs'] (http://msdn.microsoft.com/en-us/library/system.componentmodel.canceleventargs.aspx); no es mucho más básico que eso. –

+0

Buscando en Google Tengo la sensación de que tener EventArgs mutables no es realmente algo que uno debería hacer, probablemente porque alguien lo ha usado mal en algún momento. Gracias –

+0

Al igual que las cosas, tiene un lugar y tiempo para usarlo, usarlo de la manera incorrecta y el lugar es malo, pero eso no lo hace malo. – MikeT

Respuesta

41

Hazte la siguiente pregunta: "cuando publico un evento, ¿deseo que cualquier suscriptor modifique alguno de los valores de EventArgs"? Si la respuesta es no, p. está transmitiendo información de solo lectura y luego hace que la clase sea inmutable; sin embargo, si necesita algún comentario de un suscriptor, haga que las propiedades que deban modificarse se puedan modificar.

Para aclarar, en un ejemplo de difusión, queremos decirle algo a cualquier suscriptor pero no permitir que alteren el valor.

public class ProgressEventArgs : EventArgs 
{ 
    public ProgressEventArgs(int current) 
    { 
     this.Current = current; 
    } 

    public int Current { get; private set; } 
} 

Igualmente, también podríamos plantear un evento para solicitar información que la clase en sí misma desconoce.

public class FeedbackEventArgs : EventArgs 
{ 
    public bool ShouldContinue { get; set; } 
    public string Reason { get; set; } 
} 
+0

Me haya gustado esto, muestra las preguntas correctas para hacerse. –

+2

Sé que esto es antiguo, pero me gustaría señalar que uno debe tener cuidado al usar este enfoque, ya que puede haber más de un suscriptor por evento, pero sería el mismo objeto de evento que se transmite, por lo que utilizar setters simples podría da como resultado que se sobrescriban los datos. – Pharap

+0

@Pharap ¡buen punto! En el ejemplo mutable, sería un caso de "última escritura gana" –

2

No tengo conocimiento de ninguna recomendación contra heredar de EventArgs; por lo que sé, heredar de él es una buena práctica.

Como principio general, sugiero que haga que sus clases derivadas sean inmutables. Eso hará que sea mucho más seguro pasar entre hilos en caso de que necesite hacerlo. La forma más sencilla de hacerlo es declarar sus propiedades como { get; private set; }, y solo establecerlas en el constructor. Obviamente no puedes hacer eso con el caso de uso específico que tienes en la pregunta, pero debes hacerlo siempre que sea posible.

+0

+1 - de acuerdo. Usó este método muchas veces. – ChrisBD

+0

sí, simplifiqué demasiado el ejemplo, el único parámetro mutable sería el booleano. La pregunta era usar eventos para pasar datos al invocador, básicamente como un canal bidireccional, sin heredar EventArgs. El único problema que puedo ver sería con múltiples oyentes/hilos, pero la especificación en la que se usará esto no permite que –

7

Puede utilizar la clase EventArgs mediante el enfoque de Tipos genéricos. En este ejemplo, voy a utilizar la clase Rect con como tipo de retorno:

public EventHandler<Rect> SizeRectChanged; 

provocar el evento:

if(SizeRectChanged != null){ 
    Rect r = new Rect(0,0,0,0); 
    SizeRectChanged(this,r); 
} 

escuchar el evento:

anyElement.SizeRectChanged += OnSizeRectChanged; 

public void OnSizeRectChanged(object sender, Rect e){ 
    //TODO abything using the Rect class 
    e.Left = e.Top = e.Width = e.Height = 50; 
} 
+1

Esto no funcionará porque EventHandler tiene la restricción de 'donde TEventArgs: EventArgs'. Esto significa que el tipo genérico debe derivarse de EventArgs. Intentar usar un Rect dará como resultado un error de compilación. – BrandonLWhite

+4

La restricción para heredar EventArgs se ha eliminado en .net 4.5. – Dashu

Cuestiones relacionadas