Domanda

Ho una collezione personalizzata che sto aggiungendo un evento ValidateItem a. Questo evento ValidateItem sarà chiamato ogni volta che un elemento viene aggiunto o aggiornato nella raccolta personalizzata.

Voglio permettere classi derivate di poter sottoscrivere l'evento e determinare la loro propria logica per se un elemento è "valido" e potenzialmente impedire che venga aggiunto alla collezione se è "valido".

Ma io sto cercando di capire come lasciare che il chiamante all'evento sapere che cosa sta succedendo e come passare le informazioni su ciò che sta accadendo di nuovo.

I miei EventArgs personalizzati ereditano da CancelEventArgs così ho la possibilità di passare il bit Annulla al chiamante utilizzando tale. Ma non ho mai visto i casi in cui le informazioni di errore (codici di errore, messaggi, ecc) viene passato di nuovo in questo modo, quindi mi chiedo se questo potrebbe non essere l'approccio migliore.

Devo solo aggiungere eventuali dati di errore che desidero passare di nuovo alla mia ordinazione classe EventArgs, ci sono buone ragioni a favore o contro questo? o ci sono altri modi migliori per ottenere questo risultato?

Questa è la mia classe 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; }
}

UPDATE: Suppongo che un'altra altra opzione sarebbe quella di utilizzare qualcosa di simile:

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

metodo nelle classi derivate. Anche se io tendo a preferire evitando fuori parametri ...

Se qualcuno ha qualche idea sui pro ei contro di ogni approccio Mi piacerebbe sentire em!

Grazie, Max

È stato utile?

Soluzione

Uso degli eventi per questo non è probabilmente il miglior approccio progettuale.

Poiché si tratta di una classe che eredita che sarebbe override questo comportamento, il metodo deve essere contrassegnato come protetto e virtuale:

protected virtual bool Validate(object item);

Anche io non mi piace utilizzare out sui parametri, in modo seguendo il tuo istinto iniziale da utilizzare EventArgs, probabilmente si dovrebbe creare una classe per incapsulare i risultati della convalida.

Esempio:

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

Il metodo sarebbe allora:

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

   // validate and set results values accordingly

   return result;
}

I pro ei contro di utilizzare questo sopra gli eventi sono che gli eventi sono destinati ad essere utilizzati quando si desidera pubblicare un'azione o informazioni a più abbonati. Gli abbonati sono classi che non si sa nulla. Non ti importa chi sono o quello che fanno. Non dovrebbero mai veramente passare informazioni alla classe di notifica sia. Dovrebbero solo elaborare le informazioni evento data a loro.

Nel vostro caso, la classe ereditata è il tuo unico abbonato. In cima a che si vuole essere in grado di passare le informazioni utili Torna alla classe genitore. L'ereditarietà si inserisce questo comportamento desiderato molto meglio, e permette anche di implementare facilmente i diversi tipi di classe di convalida. Con gli eventi, si dovrà continuare a digitare il codice per collegare i gestori di eventi più e più volte (molto brutto IMO).

Altri suggerimenti

Non credo che quello che si sta descrivendo in realtà si adatta l'osservatore, modello osservabile che normalmente vedere con gli eventi.

Dal momento che queste sono le classi avrei probabilmente guardare alla virtualizzazione del metodo di convalida degli oggetti e con i bambini forniscono una routine di convalida specifica. Derivano

Bene, se si crea i propri eventi di validazione personalizzati, insieme ad argomenti di eventi di validazione personalizzata, vorrei assumere si preferisce passare di nuovo i codici di stato / errore piuttosto che generare eccezioni se qualcosa non convalida.

In questo caso, se si vuole avere la convalida che non generare eccezioni, allora sì, mi piacerebbe aggiungere i campi necessari per le vostre args eventi personalizzati - sono personalizzati già, quindi non c'è alcuna ragione per non estendere la loro in base alle proprie esigenze: -)

Marc

Un paio di pensieri veloci:

Vorrei fare le proprietà di sola lettura per conformarsi al modello "normale" delle classi EventArgs.

Forse le proprietà relative alle informazioni di errore devono essere avvolti insieme in una classe ErrorInformation (che renderebbe un po 'più facile per passare le informazioni intorno ad altri metodi).

Una domanda: che cosa si utilizza la proprietà EventArgs per

?

args di eventi personalizzati vengono utilizzate in modo specifico per passare le informazioni da e verso i gestori di eventi, quindi sì, sono un buon posto dove metterli.

L'altra opzione sarebbe quella di un'eccezione -. Questo è abbastanza mano pesante, ma dovrebbe smettere di altri gestori di eventi di essere giustiziato per l'evento

EventArgs e CancelEventArgs non hanno alcun membro per portare informazioni al sottoscrittore. Quindi, che normalmente ereditare da una di queste classi e aggiungere uno o più membri per trasportare informazioni. È inoltre possibile effettuare la classe generica, in modo che non c'è bisogno di fare una nuova classe EventArgs ogni volta che si dispone di dati diversi da inviare.

Infine, invece di fare il proprio tipo di ItemValidationEventHandler delegato, è possibile utilizzare EventHandler<T>, dove T è il tipo di parametro EventArgs.

Inoltre, non è necessario l'EventArgs = membro e.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top