2010-05-12 15 views
6

Nel mio livello di dominio tutti gli oggetti di dominio emettono eventi (di tipo InvalidDomainObjectEventHandler) per indicare lo stato non valido quando viene chiamata la proprietà IsValid.C#: Collega tutti gli eventi dall'oggetto nella singola istruzione

Su un codebehind aspx, devo legare manualmente gli eventi per l'oggetto del dominio in questo modo:

_purchaseOrder.AmountIsNull += new DomainObject.InvalidDomainObjectEventHandler(HandleDomainObjectEvent); 
_purchaseOrder.NoReason += new DomainObject.InvalidDomainObjectEventHandler(HandleDomainObjectEvent); 
_purchaseOrder.NoSupplier += new DomainObject.InvalidDomainObjectEventHandler(HandleDomainObjectEvent); 
_purchaseOrder.BothNewAndExistingSupplier += new DomainObject.InvalidDomainObjectEventHandler(HandleDomainObjectEvent); 

Si noti che lo stesso metodo viene chiamato in ogni caso, poiché la classe dei InvalidDomainobjectEventArgs contiene il messaggio da visualizzare .

Esiste un modo per scrivere una singola istruzione per collegare tutti gli eventi di tipo InvalidDomainObjectEventHandler in una volta sola?

Grazie

David

risposta

0

Ho dato un'occhiata al suggerimento di Bob Sammers. Il compilatore non è stato simpatia il metodo .Dove del EventInfo [] restituito da GetEvents(), ma ho cambiato un po 'il codice al seguente:

private void HookUpEvents() 
{ 
    Type purchaseOrderType = typeof (PurchaseOrder); 
    var events = purchaseOrderType.GetEvents(); 
    foreach (EventInfo info in events) 
    { 
    if (info.EventHandlerType == typeof(Kctc.Data.Domain.DomainObject.InvalidDomainObjectEventHandler)) 
    { 
     info.AddEventHandler(_purchaseOrder, new Kctc.Data.Domain.DomainObject.InvalidDomainObjectEventHandler(HandleDomainObjectEvent)); 
    } 
    } 
} 

Dopo ho aggiunto questo metodo per la pagina, tutto ha funzionato assolutamente hunky dory. E posso aggiungere eventi all'oggetto dell'ordine di acquisto senza dover ricordare di collegarli singolarmente, il che è esattamente quello che volevo.

5

Non credo che si può fare questo in un unico prospetto .. Ma si può rendere il codice più readible come questo:

_purchaseOrder.AmountIsNull += HandleDomainObjectEvent; 
_purchaseOrder.NoReason += HandleDomainObjectEvent; 
_purchaseOrder.NoSupplier += HandleDomainObjectEvent; 
_purchaseOrder.BothNewAndExistingSupplier += HandleDomainObjectEvent; 

Oltre a questo - sembra che la risposta non sia :(

+0

'No can do' è ancora una buona risposta! Grazie – David

0

Si potrebbe considerare di mettere i gestori di eventi in un'interfaccia, quindi si collega l'interfaccia:

public interface IPurchaseOrderObserver 
{ 
    void AmountIsNullEventHandler(WhateverArgs); 
    void NoReasonEventHandler(WhateverArgs); 
    void NoSupplierEventHandler(WhateverArgs); 
    void BothNewAndExistingSupplierEventHandler(WhateverArgs); 
} 

_purchaseOrder.RegisterObserver(DomainObject); 

È possibile inserire queste quattro righe nel metodo RegisterObeserver oppure sostituire gli eventi e chiamare direttamente le interfacce.

+0

Non sono sicuro di averlo seguito, ma sembra comunque che io debba menzionare direttamente tutti gli eventi da qualche parte, nell'interfaccia se non nella pagina web ... è giusto? – David

+0

Sì, è necessario citare tutti gli eventi da qualche parte, ma solo su un singolo posto. –

2

È possibile utilizzare la riflessione per eseguire automaticamente questa operazione. Penso che si desidera qualcosa di simile:

public static void WireEvents(object subject) 
{ 
    Type type = subject.GetType(); 

    var events = type.GetEvents() 
     .Where(item => item.EventHandlerType == typeof(InvalidDomainObjectEventHandler)); 

    foreach (EventInfo info in events) 
     info.AddEventHandler(subject, new InvalidDomainObjectEventHandler(HandleDomainObjectEvent)); 
} 

Poi, tutto quello che dovete fare quando si crea un nuovo oggetto è questa:

PurchaseOrder _purchaseOrder = new PurchaseOrder(); 
HelperClass.WireEvents(_purchaseOrder); 

Non dimenticate che c'è una riduzione delle prestazioni con la riflessione questo sarà evidente se crei PurchaseOrder s e altri oggetti simili in grandi numeri.

Modifica - altre note: è necessaria una direttiva using System.Reflection. Allo stato attuale, questo codice richiede C# 3 per la parola chiave var e .net framework 3.5 per il metodo Where() (e - se non viene generato automaticamente - using System.Linq;).

Come David ha fatto in una risposta successiva, può essere riscritto senza modificare la funzionalità di base per le versioni precedenti.

+0

Wow! Posso solo dire grazie! – David

+0

Non sono riuscito a far accettare al compilatore il metodo .Where, ma ho riscritto leggermente il codice e l'ho ripubblicato. Grazie mille per il vostro aiuto! – David

+0

Hmmm. Oggi non sto andando molto bene! Ancora una volta, questo codice è stato testato e attualmente ho una copia funzionante nel mio editor di codice. La mia ipotesi è che non siamo sulla stessa versione. Non hai detto cosa avevi scelto come target, ma forse avrei dovuto dire che questo codice funzionerà solo su VS2008/.net 3.5 verso l'alto. –

3

È possibile creare un evento di aggregazione in qualche classe di base (o in qualche classe di supporto, o nella classe PurchaseOrder in sé, se si ha accesso ad esso):

abstract class BaseOrderPage : Page { 

    PurchaseOrder _purchaseOrder = new PurchaseOrder(); 

    ... 

    public event InvalidDomainObjectEventHandler InvalidDomainObjectEvent { 
    add { 
     _purchaseOrder.AmountIsNull += value; 
     _purchaseOrder.NoReason += value; 
     _purchaseOrder.NoSupplier += value; 
     _purchaseOrder.BothNewAndExistingSupplier += value; 
    } 
    remove { 
     _purchaseOrder.AmountIsNull -= value; 
     _purchaseOrder.NoReason -= value; 
     _purchaseOrder.NoSupplier -= value; 
     _purchaseOrder.BothNewAndExistingSupplier -= value; 
    } 
    } 

} 

E poi basta usarlo nel classi derivate:

InvalidDomainObjectEvent += new DomainObject.InvalidDomainObjectEventHandler(HandleDomainObjectEvent); 

C# 2.0 e superiori:

InvalidDomainObjectEvent += HandleDomainObjectEvent; 

ho usato th è tecnica con successo per aggregare la classe events of the FileSystemWatcher.

+0

Non l'ho mai visto prima, grazie! – David

Problemi correlati