События предметной области (стиль Udi) и попытки обойти шаблон сервисного уровня

У меня есть деликатная проблема, связанная с тем, что у меня есть работающее решение с событиями AutoFac, CommonServiceLocator и домена Udi (http://www.udidahan.com/2009/06/14/domain-events-salvation/). Я позволил Autofac установить ServiceProvider в загрузчике MVC. Но меня раздражают две вещи: 1) События домена вызываются статическим методом, который использует CommonServiceLocator. Это затрудняет модульное тестирование, а также скрывает некоторые функции Autofac, которые мне нравятся. Это приводит меня к... 2) Мои события потребляются IEventSubscriber, где T — это DomainEvent. Но сценарий таков, что мне нравится иметь несколько подписчиков на одно событие. Это означает, что я получаю несколько подписчиков, когда вызываю событие.

 IEnumerable<IEventSubscriber<T>> registeredHandlers =
                    ServiceLocator.Current.GetAllInstances<IEventSubscriber<T>>();

Но я пометил эти экземпляры подписчиков с помощью метаданных через AutoFac:

   builder.RegisterType<CreateNewRevisionEvent>().AsImplementedInterfaces()
                   .WithMetadata<EventSubsriberMetadata>(x => x.For(order => order.Order, 1));

и класс метаданных:

public class EventSubsriberMetadata
    {
        public int Order { get; set; }
    }

Итак, вопрос. Я хотел бы добиться того, чтобы я мог каким-то образом использовать абстрактную фабрику (не решать 1), просто переместить проблему в другое место), AutoFac Delegate Factory (Func‹> не очень доволен дженериками) или просто простая инъекция в диспетчер событий домена?

Что меня убивает, так это то, что я хотел бы избежать зависимостей в сборке Domain.Core. Я знаю, что сегодня у меня есть зависимость от CommonServiceLocator. Но использовать DI в классе Base Entity (то, к чему это приводит), я не знаю простого способа. Я видел демонстрацию Никласа Блумхардта, где AutoFac внедряет DomainEventDispatcher в объекты через перехватчики NHibernate и может отправлять события во время Up/Down в постоянство. Аккуратное решение. Но я использую Entity Framework 5 и тоже надеюсь на более простое решение.

С нетерпением жду ответа или хотя бы обсуждения этой темы. Я думаю, что многие люди останавливаются, когда они подходят к этой проблеме. И, может быть, просто: «Хорошо, мы используем CSL только для событий», и они также устанавливают границы для модульного тестирования. - "Мы пропускаем модульное тестирование для событий". Это не проблема здесь :)

/С наилучшими пожеланиями Магнус


person Magnus Backeus    schedule 18.10.2013    source источник
comment
Возможно, вы имеете в виду шаблон Service Locator вместо шаблона Service Layer в заголовке вопроса?   -  person Lightman    schedule 08.11.2015


Ответы (1)


Ваша задача сводится к отделению кода вашего домена от таких зависимостей, как Autofac, CommonServiceLocator. Это хорошая вещь. Тем не менее, нет ничего плохого в том, чтобы иметь встроенный сервисный локатор (реестр доменных событий и повышение) в коде вашего домена. Вам просто нужно смириться с уменьшением обнаруживаемости. Существуют и другие способы достижения аналогичной цели (например, обычные события .net, сущности IObservable,...). Подписки должны происходить извне. Например, как часть создания дочерней области жизненного цикла.

Еще одна вещь, которую следует учитывать, — это когда события должны запускаться. Если вы согласны с небольшой задержкой, вы можете сделать так, чтобы объекты собирали свои события домена внутри, а в конце операции запрашивали у объектов собранные события домена, отправляя их тут же подписчикам. Обратите внимание, как эта последняя часть может происходить на уровне приложения или, по крайней мере, вне кода предметной области. Многое зависит от того, чего вы пытаетесь достичь в подписчиках событий.

Таким образом, разделение, безусловно, возможно, но оно требует проверки выбранной стратегии на соответствие вашим требованиям. Эксперимент :)

person Yves Reynhout    schedule 20.10.2013
comment
Хм, интересная новая перспектива — сбор событий вручную на уровне приложения. Ну, цель с подписчиками событий состоит в том, чтобы событие называлось так, как оно произошло. Например, NewAddressAddedToPerson, а затем один или несколько подписчиков могут воздействовать на это событие. Некоторым, возможно, придется действовать в порядке занавеса. Вот почему я хочу использовать метаданные. Я начинаю понимать, что запускать события из ядра домена будет нормально — по сравнению с работой по удалению Service Locator. Удаление зависимостей от AutoFac можно выполнить, написав свой собственный простой локатор, куда я могу обернуть Autofac и, по крайней мере, использовать метаданные... - person Magnus Backeus; 20.10.2013