C #: подключить все события от объекта в одном выражении - PullRequest
6 голосов
/ 12 мая 2010

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

В коде 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 за один раз?

Спасибо

David

Ответы [ 5 ]

5 голосов
/ 12 мая 2010

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

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

Кроме этого - похоже, что нет ответа: (

3 голосов
/ 12 мая 2010

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

2 голосов
/ 12 мая 2010

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

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() (и - если он не сгенерирован автоматически - using System.Linq;).

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

0 голосов
/ 12 мая 2010

Я посмотрел на предложение Боба Сэммерса. Компилятору не понравился метод .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 голосов
/ 12 мая 2010

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

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

_purchaseOrder.RegisterObserver(DomainObject);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...