2010-05-12 6 views
6

En mi capa de dominio, todos los objetos de dominio emiten eventos (del tipo InvalidDomainObjectEventHandler) para indicar el estado no válido cuando se llama a la propiedad IsValid.C#: conectar todos los eventos del objeto en una sola declaración

En un código subyacente aspx, tengo que conectar manualmente los eventos para el objeto de dominio de esta manera:

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

Tenga en cuenta que el mismo método se llama en cada caso, ya que la clase los InvalidDomainobjectEventArgs contiene el mensaje para mostrar .

¿Hay alguna manera de que pueda escribir una sola instrucción para conectar todos los eventos del tipo InvalidDomainObjectEventHandler de una vez?

Gracias

David

Respuesta

0

Miré la sugerencia de Bob Sammers. El compilador no era gusto el método .Where del EventInfo [] devuelto por GetEvents(), pero he cambiado ligeramente el código a la siguiente:

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)); 
    } 
    } 
} 

Después añadí este método para la página, todo funcionó absolutamente hunky dory. Y puedo agregar eventos al objeto de orden de compra sin tener que recordar conectarlos individualmente, que es exactamente lo que quería.

5

No creo que usted puede hacer esto en una sola instrucción .. Pero se puede hacer el código más readible así:

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

Aparte de eso - parece que la respuesta es no :(

+0

'No puedo hacer' sigue siendo una buena respuesta! Gracias – David

0

Podría considerar colocar los controladores de eventos en una interfaz. A continuación, conecte la interfaz:

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

_purchaseOrder.RegisterObserver(DomainObject); 

O bien coloca estas cuatro líneas en el método RegisterObeserver, o reemplaza los eventos y llama directamente a las interfaces.

+0

No estoy seguro Seguí esto, pero todavía parece que tengo que mencionar directamente todos los eventos en algún lugar, en la interfaz si no en la página web ... ¿es así? – David

+0

Sí, debe mencionar todos los eventos en algún lugar, pero solo en un solo lugar. –

2

Puede usar el reflejo para hacer esto automáticamente. Creo que quieres algo como esto:

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)); 
} 

Entonces, todo lo que tiene que hacer cuando se crea un nuevo objeto es la siguiente:

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

No hay que olvidar que hay una penalización en el rendimiento con la reflexión eso será evidente si crea PurchaseOrder sy otros objetos similares en grandes cantidades.

Editar - otras notas: necesitará una directiva using System.Reflection. Tal como está, este código necesita C# 3 para la palabra clave var y .NET Framework 3.5 para el método Where() (y, si no se genera automáticamente, using System.Linq;).

Como lo hizo David en una respuesta posterior, se puede volver a escribir sin cambiar la funcionalidad básica de las versiones anteriores.

+0

¡Guau! Solo puedo decir gracias! – David

+0

No pude hacer que el compilador aceptara el método .Where, pero reescribí el código ligeramente y lo volví a publicar. ¡Muchas gracias por su ayuda! – David

+0

Hmmm. ¡No estoy muy bien hoy! Una vez más, este código es probado y actualmente tengo una copia de trabajo en mi editor de código. Supongo que no estamos en las mismas versiones. Usted no dijo a qué estaba apuntando, pero quizás debería haber dicho que este código solo funcionará en VS2008/.net 3.5 en adelante. –

3

Puede crear un evento agregado de alguna clase de base (o de alguna clase de ayuda, o en la clase PurchaseOrder sí, si usted tiene acceso a ella):

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; 
    } 
    } 

} 

Y a continuación, sólo tiene que utilizar en el clases derivadas:

InvalidDomainObjectEvent += new DomainObject.InvalidDomainObjectEventHandler(HandleDomainObjectEvent); 

C# 2.0 y anteriores:

InvalidDomainObjectEvent += HandleDomainObjectEvent; 

he utilizado º es una técnica exitosa para agregar la clase events of the FileSystemWatcher.

+0

¡No había visto eso antes, gracias! – David

Cuestiones relacionadas