2010-05-12 49 views
6

在我的域图层中,当调用IsValid属性时,所有域对象都会发出事件(类型为InvalidDomainObjectEventHandler)以指示无效状态。C#:在单个语句中连接来自对象的所有事件

在一个aspx代码隐藏,我必须手动线了的域对象这样的事件:

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

注意,相同的方法被称为在每种情况下,因为InvalidDomainobjectEventArgs类包含要显示的消息。

有没有什么办法可以编写单条语句来一次性连接InvalidDomainObjectEventHandler类型的所有事件?

感谢

大卫

回答

0

我看着Bob Sammers的建议。编译器不顺心的EventInfo []由GetEvents()返回,但我已经略有改变的代码下面的方法。凡:

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

后,我加入这个方法的页面,它所有的工作绝对hunky dory。而且我可以将事件添加到采购订单对象,而无需记住单独挂钩,这正是我想要的。

5

我不认为你可以在一个声明中做到这一点..但是你可以让这样的代码更readible:

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

比其他 - 似乎答案是:(

+0

'不能做'仍然是一个很好的答案! 谢谢 – David 2010-05-12 11:06:17

0

您可以考虑将事件处理程序放入界面中,然后附加界面:

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

_purchaseOrder.RegisterObserver(DomainObject); 

您可以将这四行放入RegisterObeserver方法中,或者替换事件并直接调用接口。

+0

不知道我跟着这个,但似乎我仍然不得不直接提到所有事件的地方,如果不在网页中的界面......是吗? – David 2010-05-12 11:07:19

+0

是的,你需要提到所有的事件,但只在一个地方。 – 2010-05-17 10:57:30

2

您可以使用反射自动执行此操作。我想你想是这样的:

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

然后,当你创建一个新对象的所有您需要做的是这样的:

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

不要忘了,还有一个性能损失与反思如果您创建了大量的PurchaseOrder和其他类似对象,这一点将会很明显。

编辑 - 其他注意事项:您将需要一个using System.Reflection指令。就目前而言,此代码需要C#3的var关键字和.net framework 3.5的Where()方法(以及 - 如果它不是自动生成的 - using System.Linq;)。

正如David在稍后的回答中所做的那样,可以在不更改早期版本的基本功能的情况下对其进行重新编写。

+0

哇!我只能说谢谢! – David 2010-05-12 13:49:33

+0

我无法让编译器接受.Where方法,但我稍微重写了您的代码并重新发布了它。 非常感谢您的帮助! – David 2010-05-12 14:06:08

+0

嗯。我今天表现不佳!再一次,这段代码已经过测试,而且我目前在我的代码编辑器中有一份工作副本。我的猜测是我们不在同一个版本。你没有说你的目标是什么,但也许我应该说这个代码只能在VS2008/.net3.5以上的版本上运行。 – 2010-05-12 14:21:11

3

您可以创建一些基础类的聚集事件(或一些辅助类,或者在PurchaseOrder类本身,如果你有机会获得它):

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

} 

,然后只用它在派生类:

InvalidDomainObjectEvent += new DomainObject.InvalidDomainObjectEventHandler(HandleDomainObjectEvent); 

C#2.0和以上:

InvalidDomainObjectEvent += HandleDomainObjectEvent; 

我使用第技术成功地聚合了events of the FileSystemWatcher类。

+0

我以前没见过,谢谢! – David 2010-05-13 08:03:47