C#: Поднимите трубку все события от объекта в отдельном операторе

В моем доменном слое все объекты области испускают события (типа InvalidDomainObjectEventHandler) для указания на недопустимое состояние, когда свойство IsValid называют.

На aspx codebehind, я должен вручную обеспечить электричеством события для объекта области как это:

_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 сразу?

Спасибо

David

6
задан David 12 May 2010 в 10:04
поделиться

5 ответов

Я посмотрел на предложение Боба Саммерса. Компилятору не понравился метод .Where для 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));
    }
  }
}

После того, как я добавил этот метод на страницу, все сработало абсолютно безупречно. дори. И я могу добавлять события к объекту заказа на покупку, не забывая подключать их по отдельности, а это именно то, что я хотел.

0
ответ дан 10 December 2019 в 00:35
поделиться

Не думаю, что это можно сделать в одном операторе... Но вы можете сделать код более читабельным, например, так:

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

В остальном - похоже, что ответ отрицательный :(

5
ответ дан 10 December 2019 в 00:35
поделиться

Вы можете использовать отражение, чтобы сделать это автоматически. Я думаю, вам нужно что-то вроде этого:

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 s и другие подобные объекты в любых больших количествах.

Правка - другие примечания: вам понадобится директива using System.Reflection . В его нынешнем виде этому коду требуется C # 3 для ключевого слова var и .net framework 3.5 для метода Where () (и - если он не создается автоматически - с использованием System.Linq; ).

Как Дэвид сделал в более позднем ответе, его можно переписать без изменения основных функций для более ранних версий.

2
ответ дан 10 December 2019 в 00:35
поделиться

Вы можете создать агрегированное событие в некоторых базовый класс (или в каком-то вспомогательном классе, или в самом классе 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;

Я успешно использовал эту технику для агрегирования событий класса FileSystemWatcher .

3
ответ дан 10 December 2019 в 00:35
поделиться

Вы можете рассмотреть возможность поместить обработчики событий в интерфейс. Затем вы присоединяете интерфейс:

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

_purchaseOrder.RegisterObserver(DomainObject);

Вы либо помещаете эти четыре строки в метод RegisterObeserver, либо заменяете события и напрямую вызываете интерфейсы.

0
ответ дан 10 December 2019 в 00:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: