Шаблон событий домена, единая точка для постановки событий в очередьC#

Место общения программистов C#
Ответить
Anonymous
 Шаблон событий домена, единая точка для постановки событий в очередь

Сообщение Anonymous »

Я задал вопрос здесь: «Поднятие событий домена для нескольких подписчиков», и ответ привел меня к следующему шаблону, в котором я могу использовать IEventPublisher следующим образом:

Код: Выделить всё

public interface IEventPublisher
{
void Publish(T data);
}
и IEventSubscriber вот так:

Код: Выделить всё

public interface IEventSubscriber
{
void Handle(T data);
}
Проблема в том, что мне нужно передать экземпляр каждого издателя конструктору следующим образом:

Код: Выделить всё

public Service(IEventPublisher publisherThingyChanged)
{
// Set publisher to local variable
}

// then call this in a method
_publisherThingyChanged.Publish(new ThingyChangedEvent { ThingyId = model.Id});
В идеале мне хотелось бы иметь общий издатель, содержащий все IEventPublishers, чтобы я мог вызывать что-то вроде:

Код: Выделить всё

_genericPublisher.Publish(new ThingyChangedEvent { ThingyId = model.Id});
Однако я не могу понять, как это сделать, поскольку я не могу передать коллекцию IEventPublisher без определения T, как в этом примере, как ThingyChangedEvent, тогда как я хочу определить издателя на основе типа, который передается универсальному издателю.

Любые предложения очень приветствуются.

РЕДАКТИРОВАТЬ:

ОК, используя ответ ниже и некоторую информацию отсюда: http://www.udidahan.com/2009/06/14/doma ... salvation/ Я придумал следующее, но это не совсем так:

Код: Выделить всё

public interface IEventManager
{
void Publish(T args) where T : IEvent;
}
>публичный класс EventManager: IEventManager
{
Autofac.ILLifetimeScope _container;

Код: Выделить всё

public EventManager(Autofac.ILifetimeScope container)
{
_container = container;
}

//Registers a callback for the given domain event
public void Publish(T args) where T : IEvent
{
var subscribersProvider = _container.Resolve();
foreach (var item in subscribersProvider.GetSubscribersForEvent())
{
item.Handle(args);
}
}


Теперь я могу взять экземпляр IEventManager eventManager в конструкторе, разрешенном autofac, и вызвать его следующим образом:

Код: Выделить всё

_eventManager.Publish(new ThingyChangedEvent() { ThingyId = Guid.NewGuid() });
Вот что мне не нравится в этом решении:

Я не хочу использовать экземпляр ILifetimeScope в конструкторе, я хочу иметь возможность брать коллекцию IEventSubscribersProvider, но autofac не решит эту проблему, если я попрошу сказать:

Код: Выделить всё

 IEnumerable
Я смогу решить эту проблему, только если передам тип функции Publish и вызову:

Код: Выделить всё

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

Код: Выделить всё

_eventManager.Publish(new ThingyChangedEvent() { ThingyId = Guid.NewGuid() });
Думаю, есть ли у кого-нибудь предложения о том, как решить эти две проблемы, особенно проблему 1, поскольку мне не нравится устанавливать зависимость от Autofac в разных проектах. Единственное, что я могу придумать, это какой-то класс менеджера, который явно принимает то, что мне нужно, следующим образом:

Код: Выделить всё

public SomeConstructor(
IEventSubscribersProvider thingChangedSubscribeProviders,
IEventSubscribersProvider someOtherSubscribeProviders,
etc....)
{
// Maybe take the EventManager as well and add them to it somehow but would be
// far easier to take a collection of these objects somehow?
}
Большое спасибо за любые предложения.

РЕДАКТИРОВАНИЕ 2

После долгих исследований и просмотра этого решения Autofac Generic Service во время выполнения я не уверен, что смогу достичь того, чего хочу. Лучшее решение, которое я могу придумать, это:

Код: Выделить всё

public interface IEventSubscribersProviderFactory : Amico.IDependency
{
IEventSubscribersProvider Resolve() where T : IEvent;
}

public class EventSubscribersProviderFactory : IEventSubscribersProviderFactory
{
Autofac.ILifetimeScope _container;

public EventSubscribersProviderFactory(Autofac.ILifetimeScope container)
{
_container = container;
}

public IEventSubscribersProvider Resolve() where T : IEvent
{
return _container.Resolve();
}
}
А затем попросите EventManager использовать IEventSubscribersProviderFactory в конструкторе, чтобы удалить зависимость от Autofac из этого проекта.

Я пока воспользуюсь этим, но надеюсь, что найду лучшее решение в долгосрочной перспективе.>

Подробнее здесь: https://stackoverflow.com/questions/156 ... eue-events
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»