Pregunta

Tengo una colección personalizada que estoy añadiendo un evento ValidateItem a. Este evento ValidateItem será llamado cada vez que se agrega un elemento o actualiza en la colección personalizada.

Quiero permitir que las clases derivadas para poder suscribirse al evento y determinar su propia lógica de si es o no un artículo es "válida" y potencialmente prohibir que se añade a la colección si es "válido".

Pero estoy tratando de encontrar la manera de dejar que la persona que llama al evento sabe lo que está pasando y cómo pasar la información acerca de lo que está pasando en la parte posterior.

Mis EventArgs personalizados heredan de CancelEventArgs así que tengo la capacidad de pasar el bit Cancelar de nuevo a la persona que llama usando eso. Pero nunca he visto ningún caso en que la información de error (códigos de error, mensajes, etc.) se pasa de nuevo de esta manera, así que me estoy preguntando si esto podría no ser el mejor enfoque.

¿Debo agregar los datos de error que deseo pasar de nuevo a mi clase EventArgs personalizada, ¿hay buenas razones a favor o en contra de esto? o existen otras, mejores maneras de lograr esto?

Esta es mi clase EventArgs:

public delegate void ItemValidationEventHandler(object sender, ItemValidationEventArgs e);

public class ItemValidationEventArgs : CancelEventArgs
{
    public ItemValidationEventArgs(object item, ObjectAction state, EventArgs e)
    {
        Item = item;
        State = state;
        EventArgs = e;
    }

    public ItemValidationEventArgs(object item, ObjectAction state) : this(item, state, new EventArgs())
    {
    }

    public ItemValidationEventArgs() : this(null, ObjectAction.None, new EventArgs())
    {
    }

    // is there a better way to pass this info?
    public string ErrorMessage {get; set;}
    public int ErrorNumber {get;set;}

    public object Item { get; private set; }
    public ObjectAction State { get; private set; }

    public EventArgs EventArgs { get; private set; }
}

ACTUALIZACIÓN: supongo que otra otra opción sería utilizar algo como esto:

virtual bool Validate(object item, ObjectAction action, out string errorMessage) 

método en las clases derivadas. Aunque tiendo a preferir evitar cabo parámetros ...

Si alguien tiene alguna idea sobre los pros y los contras de cada enfoque Me encantaría escuchar em!

Gracias, Max

¿Fue útil?

Solución

El uso de eventos para esto probablemente no es el mejor enfoque de diseño.

Dado que es una clase que hereda que ser de primer orden este comportamiento, el método debe ser marcado como protegido y virtual:

protected virtual bool Validate(object item);

Yo también no me gusta usar out en parámetros, por lo que después de sus instintos iniciales de utilizar EventArgs, probablemente debería crear una clase para encapsular los resultados de la validación.

Ejemplo:

class ValidationResult
{
     public string ResultMessage{get;set;}
     public bool IsValid {get;set;}
}

Su método sería entonces:

protected virtual ValidationResult Validate(object item)
{
   ValidationResult result = new ValidationResult();

   // validate and set results values accordingly

   return result;
}

Los pros y los contras de la utilización de esta sobre los eventos son eventos que están destinados a ser utilizados cuando se desea publicar una acción o información a múltiples abonados. Los suscriptores son clases que no sabes nada. No te importa lo que son o lo que hacen. Deben nunca realmente pasar información a la clase notifica tampoco. Que sólo debe procesar la información del evento que se les da.

En el ejemplo, su clase heredada es su único suscriptor. Además de eso usted quiere ser capaz de pasar información útil de nuevo a la clase padre. La herencia se ajusta a este comportamiento deseado mucho mejor, y también le permite implementar fácilmente diferentes tipos de clase de validación. Con eventos, que tendría que seguir escribiendo código para asociar controladores de eventos una y otra vez (muy feo OMI).

Otros consejos

No creo que lo que usted está describiendo realmente se ajusta el observador, patrón observable que normalmente ver con los acontecimientos.

Dado que estos son clases que probablemente se vería a la virtualización del método de validación de los objetos y hacer que los niños proporcionan una rutina de validación específico. Derivan

Bueno, si crea sus propios eventos de validación personalizada, junto con el evento args validación personalizada, asumiría prefiere pasar de nuevo los códigos de estado / error en lugar de lanzar excepciones si algo no valida.

En este caso, si usted quiere tener la validación de que no va a lanzar excepciones, entonces sí, me gustaría añadir los campos que necesite para su evento args personalizados - son personalizados ya, así que no hay razón para no extenderlos para satisfacer sus necesidades: -)

Marc

Un par de pensamientos rápidos:

Me gustaría hacer las propiedades de sólo lectura para ajustarse al patrón "normal" de las clases EventArgs.

Tal vez las propiedades relacionadas con la información de error deben ser envueltos juntos en alguna clase ErrorInformation (que habría que sea un poco más fácil pasar esa información en torno a otros métodos).

Una pregunta: ¿qué se utiliza la propiedad EventArgs para

?

args de eventos personalizados se utilizan específicamente para transmitir información hacia y desde los controladores de eventos, así que sí, son un buen lugar para ponerlas.

La otra opción sería la de lanzar una excepción -. Esto es bastante mano dura, pero debe dejar de otros controladores de eventos de ser ejecutado para el evento

EventArgs y CancelEventArgs no tienen ningún miembro para llevar la información al abonado. Por lo tanto, normalmente heredar de una de estas clases y añadir uno o más miembros para llevar información. También puede hacer que su clase genérica, de modo que usted no tiene que hacer una nueva clase EventArgs cada vez que tenga diferentes datos que enviar.

Por último, en lugar de hacer su propio tipo ItemValidationEventHandler delegado, puede utilizar EventHandler<T>, donde T es el tipo de su parámetro EventArgs.

Además, no es necesario el EventArgs e = miembro.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top