Me estoy preparando para crear una clase EventArgs genérica para argumentos de eventos que llevan un solo argumento:
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 hacer eso, ¿C # tiene la misma característica integrada en el lenguaje? Creo recordar haberme encontrado con 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 C # proporciona una? Gracias por tu ayuda.
Eventhandler<T>
EventArgs<T>
en código basado en CAB / SCSF. Es bastante común en aplicaciones CAB / SCSF. Aunque no es parte del marco, no es un EventArgs <T> aplicación.Respuestas:
No. Probablemente estaba pensando
EventHandler<T>
, lo que le permite definir el delegado para cualquier tipo específico de EventArgs.Sin
EventArgs<T>
embargo, personalmente no creo que encaje tan bien. La información utilizada como "carga útil" en los argumentos de evento 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"?)fuente
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 eventos / argumentos, estilo de firma? La cosa es que, no todo lo que está en .NET, o que 'falta en' para el caso, es 'bueno': MS se ha 'corrigido' a sí mismo durante años ... Yo diría que simplemente vaya y cree uno, como lo hice yo porque lo necesitaba así y me ahorré mucho tiempo
fuente
Existe. Al menos, lo hace ahora.
Puede encontrar
DataEventArgs<TData>
en algunos ensamblados / espacios de nombres diferentes de Microsoft, por ejemplo, Microsoft.Practices.Prism.Events . Sin embargo, estos son espacios de nombres que puede que no le resulte natural incluir en su proyecto, por lo que puede usar su propia implementación.fuente
En caso de que elija no usar Prism , pero aún así le gustaría probar un enfoque genérico de EventArgs .
public class GenericEventArgs<T> : EventArgs { public T EventData { get; private set; } public GenericEventArgs(T EventData) { this.EventData = EventData; } }
// Utilice el siguiente código de muestra para declarar el evento ObjAdded
public event EventHandler<GenericEventArgs<TargetObjType>> ObjAdded;
// Usa el siguiente código de muestra para generar el evento ObjAdded
private void OnObjAdded(TargetObjType TargetObj) { if (ObjAdded!= null) { ObjAdded.Invoke(this, new GenericEventArgs<TargetObjType>(TargetObj)); } }
// Y finalmente puedes suscribirte a tu evento ObjAdded
SubscriberObj.ObjAdded += (object sender, GenericEventArgs<TargetObjType> e) => { // Here you can explore your e.EventData properties };
fuente
NO HAY ARGS GENÉRICOS INTEGRADOS. Si sigue el patrón Microsoft manejador de sucesos, a continuación, a implementar sus derivados EventArgs como usted sugiere:
public class MyStringChangedEventArgs : EventArgs { public string OldValue { get; set; } }
.SIN EMBARGO, si la guía de estilo de su equipo acepta una simplificación, su proyecto puede utilizar 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, los proyectos de PoC utilizan el último enfoque. Sin embargo, en aplicaciones profesionales, tenga en cuenta la justificación de policía FX # CA1009: https://msdn.microsoft.com/en-us/library/ms182133.aspx
fuente
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 el uso posterior de una versión derivada del tipo.
fuente
IEventArgs
, pero las únicas clases que pueden ser genéricas con respecto a los parámetros de tipo genérico son los delegados a los que no se alimentaráDelegate.Combine
. Los delegados que se utilizarán conDelegate.Combine
no deben ser covariantes, ya que se puede almacenar, por ejemplo, anAction<DerivedType>
en un campo de tipoAction<BaseType>
, pero un intento posteriorCombine
con una instancia deAction<BaseType>
fallará.La razón por la que esto no existe es porque lo que terminaría sucediendo es que lo implementas, y luego, cuando vayas a completar la T, debes crear una clase con propiedades inequívocas fuertemente tipadas que actúe como la bolsa de datos para tu evento arg, pero a la mitad de la implementación, se da cuenta de que no hay razón para que no haga que la clase herede de EventArgs y la llame buena.
A menos que solo desee una cadena o algo igualmente básico para su bolsa de datos, en cuyo caso probablemente haya clases EventArgs estándar en .NET que están destinadas a servir cualquier propósito simple al que se esté dirigiendo.
fuente