2010-07-22 25 views
74

Me estoy preparando para crear una clase EventArgs args genérico para eventos que llevan un solo argumento:¿.NET tiene incorporado EventArgs <T>?

public class EventArg<T> : EventArgs 
{ 
    // Property variable 
    private readonly T p_EventData; 

    // Constructor 
    public EventArg(T data) 
    { 
     p_EventData = data; 
    } 

    // Property for EventArgs argument 
    public T Data 
    { 
     get { return p_EventData; } 
    } 
} 

Antes de hacerlo, qué C# tienen la misma característica incorporada en el lenguaje? Me parece recordar haber encontrado algo así cuando salió C# 2.0, pero ahora no puedo encontrarlo.

O para decirlo de otra manera, ¿tengo que crear mi propia clase genérica EventArgs, o la proporciona C#? Gracias por tu ayuda.

+8

Es posible que haya visto '' eventHandler

+1

Es posible que haya visto '' 'EventArgs ' '' en el CAB/código basado en SCSF. Es bastante común en aplicaciones CAB/SCSF. Si bien no forma parte del marco, * hay * una implementación de EventArgs . –

Respuesta

61

No. Probablemente estaba pensando en EventHandler<T>, que le permite definir el delegado para cualquier tipo específico de EventArgs.

Personalmente, no creo que EventArgs<T> sea tan bueno de forma, sin embargo. La información utilizada como "carga útil" en el evento args debería ser, en mi opinión, una clase personalizada para que su uso y las propiedades esperadas sean muy claras. El uso de una clase genérica evitará que pueda poner nombres significativos en su lugar. (¿Qué representa "Datos"?)

+39

En aplicaciones centradas en datos, similares a MPI, es bastante común ver un EventArgs en lugar para el procesamiento de datos para que los desarrolladores puedan aprovechar un sistema integrado de suscripción/registro (Eventos y delegados .NET), como no tiene ningún sentido crear subclases EventArgs solo para transportar datos. Si su intención es transportar datos, podría decirse que tiene más sentido definir un EventArgs , puede hacer una subclase para usos discretos SIN TENER en cuenta los datos que se transportan. TL: DR Esta primera parte de esta respuesta es completa y precisa, la segunda parte es subjetiva/opinión. –

+1

Supongo que tienes razón ... resiste la pereza que me tiene aquí. Es como cuando los desarrolladores perezosos usan Tuple <,>. Cosas terribles – CRice

+0

Un buen punto, pero esto básicamente sería hacer lo mismo que hizo Microsoft cuando agregaron la propiedad Tag a las clases de controles. Por supuesto, solo porque la MS lo hizo, no lo hace bien. –

-4

La razón por la que esto no existe es porque lo que terminaría sucediendo es que implemente esto, y luego, cuando vaya a completar la T, debe crear una clase fuertemente tipada inequívoca propiedades que actúan como la bolsa de datos para su evento, pero a mitad de la implementación se da cuenta de que no hay ninguna razón por la que no haga que esa clase herede de EventArgs y lo llame bueno.

A menos que solo desee una cadena o algo similarmente básico para su bolsa de datos, en cuyo caso probablemente haya clases de EventArgs estándar en .NET que están destinadas a servir a cualquier propósito simple que esté recibiendo.

+0

-1. Tengo EXACTAMENTE esta situación ahora, y mi carga útil sería un objeto inmutable que es un "mensaje" que proviene de un autobús ... y también está en otros lugares. Las EventArgs personalizadas ... crean una clase redundante aquí. Inusual, pero la aplicación es así. – TomTom

1

El problema con un tipo genérico es que incluso si DerivedType hereda de BaseType, EventArgs (DerivedType) no heredaría de EventArgs (BaseType). El uso de EventArgs (BaseType) evitaría más adelante el uso de una versión derivada del tipo.

+2

Esto es patentemente falso. Consulte "Covarianza y contradicción en genéricos - Microsoft.com" http://msdn.microsoft.com/en-us/library/dd799517.aspx –

+1

@ShaunWilson: ¿Qué aspecto es falso? Se podría definir una interfaz covariante 'IEventArgs', pero las únicas clases que pueden ser genéricas con respecto a los parámetros de tipo genérico son los delegados que no se alimentarán a' Delegate.Combine'. Los delegados que se utilizarán con 'Delegate.Combine' no deben ser covariantes, ya que uno puede almacenar, p. una 'Acción ' en un campo de tipo 'Acción ', pero un intento posterior de' Combinar 'eso con una instancia de' Acción ' fallará. – supercat

26

Debo decir que no entiendo a todos los 'puristas' aquí. es decir, si ya tiene una clase de bolsa definida, que tiene todos los detalles, propiedades, etc., ¿por qué el truco crea una clase adicional innecesaria solo para poder seguir el mecanismo de evento/args, estilo de firma? Lo que pasa es que no todo lo que hay en .NET, o que "falta" para el caso, es "bueno". La MS se ha estado "corrigiendo" por años ... Yo diría que solo ve y crea uno como Lo hice - porque lo necesitaba así - y me ahorré mucho tiempo,

+2

En este caso, el punto "purista" es hacer que la intención sea lo más clara posible. En una aplicación de producción, tengo docenas de estas clases de EventArgs.Dentro de un año, será más fácil entender lo que hice si sigo los consejos de Reed y creo una clase personalizada de EventArgs. –

+8

no quiso etiquetar a nadie :) punto está en el 'genérico' en el evento - si solo necesita una docena de eventos diferentes, está bien. Pero si no conoce la naturaleza de la T de antemano, eso solo se conoce en el tiempo de ejecución, bueno, necesita un evento genérico. Por lo tanto, si tiene una aplicación que trata buena parte de w/genéricos, un número arbitrario de tipos, desconocido, entonces también necesita eventos genéricos. o sea, no hay una solución clara para cada problema, la regla general es solo una regla general, y eso es lo que quise decir con puristas, cada solución es diferente, debe sopesar las cosas, los pros y los contras – NSGaga

7

Sí existe. Al menos, ahora sí.

Puede encontrar DataEventArgs<TData> en algunos ensamblados/espacios de nombres de Microsoft diferentes, por ejemplo Microsoft.Practices.Prism.Events. Sin embargo, estos son espacios de nombres que quizás no encuentre naturales para incluir en su proyecto, por lo que puede usar su propia implementación.

+0

He estado tratando de encontrar recomendaciones y consideraciones con respecto a cuándo y por qué usar una clase tan genérica de EventArgs. Ver también: http://stackoverflow.com/questions/15766219/ok-to-use-dataeventargstdata-instead-of-customized-event-data-class –

+0

A continuación, se detallan algunos aspectos a tener en cuenta al decidir utilizar un EventArgs genérico: http://stackoverflow.com/questions/129453/net-eventhandlers-generic-or-no/129613#129613 –

6

En caso de que elija no utilizar Prism, pero aún así le gustaría probar un enfoque genérico EventArgs.

public class GenericEventArgs<T> : EventArgs 
{ 
    public T EventData { get; private set; } 

    public GenericEventArgs(T EventData) 
    { 
     this.EventData = EventData; 
    } 
} 

// Utiliza el siguiente código de ejemplo para declarar ObjAdded caso

public event EventHandler<GenericEventArgs<TargetObjType>> ObjAdded; 

// Utiliza el siguiente código de ejemplo para elevar ObjAdded caso

private void OnObjAdded(TargetObjType TargetObj) 
{ 
    if (ObjAdded!= null) 
    { 
     ObjAdded.Invoke(this, new GenericEventArgs<TargetObjType>(TargetObj)); 
    } 
} 

// Y finnaly puede suscribir su ObjAdded evento

SubscriberObj.ObjAdded += (object sender, GenericEventArgs<TargetObjType> e) => 
{ 
    // Here you can explore your e.EventData properties 
}; 
3

NO HAY ARGS GENERICOS INCORPORADOS. Si sigue el patrón Microsoft EventHandler, entonces implementa sus EventArgs derivados como sugirió: public class MyStringChangedEventArgs : EventArgs { public string OldValue { get; set; } }.

Sin embargo - si su guía de estilo de equipo acepta una simplificación - su proyecto puede utilizar una serie de eventos ligeros, como este:

public event Action<object, string> MyStringChanged; 

uso:

// How to rise 
private void OnMyStringChanged(string e) 
{ 
    Action<object, string> handler = MyStringChanged; // thread safeness 
    if (handler != null) 
    { 
     handler(this, e); 
    } 
} 

// How to handle 
myObject.MyStringChanged += (sender, e) => Console.WriteLine(e); 

Por lo general, un proyectos de PoC utiliza el último enfoque . En applicatons profesionales, sin embargo, estar al tanto de FX policía justificación # CA1009: https://msdn.microsoft.com/en-us/library/ms182133.aspx

Cuestiones relacionadas