Обработчики сообщений со строгим типом в Mediator в C# - PullRequest
0 голосов
/ 13 января 2020

У меня сейчас проблема с реализацией решения для межобъектной коммуникации в моем текущем проекте. Я решил опробовать такой объект, как шаблон посредника, где объекты общаются друг с другом с помощью сообщений через широковещательную передачу посреднику. Затем посредник отправляет сообщение объектам, которые специально прослушивали передаваемое сообщение.

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

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

В идеале, я бы хотел, чтобы интерфейс publi c выглядел следующим образом:

class Mediator
{
    private Dictionary<Type, ???> handlers; // how to I retain the strongly-typed handler


    public void RegisterForBroadcast<T>(Action<T> handler) where T : IMessage
    {
        // how can I turn the strongly-typed handler into something I can use?
    }

    public void UnregisterFromBroadcast<T>(Action<T> handler) where T : IMessage
    {
    }

    public void Broadcast<T>(T message) where T : IMessage
    {
        // how do I get the collection of handlers from where it's stored and use it?
    }
}

class Receiver
{
     private Mediator mediator; 

     public Receiver()
     { 
          mediator = GetMediator();
          mediator.RegisterForBroadcast<SpecificMessage>(MessageHandler);
     }

     private void MessageHandler(SpecificMessage msg)
     {
          CustomData data = msg.GetCustomData();
     }
}

class BroadcastingObject
{
     private Mediator mediator;
     private SpecificData data;

     public BroadcastingObject()
     {
          mediator = GetMediator();
          specificData = GetSpecificData();
     }

     public void TimeToBroadcast()
     {
          mediator.Broadcast<SpecificMessage>(new SpecificMessage(specificData));
     }
}

Возможно ли в этом проекте использовать обработку сообщений со строгой типизацией, которую я хотеть? Если да, то как мне это сделать?

Изменить - добавлен код, описывающий, как я хочу, чтобы объект отправителя и получателя взаимодействовал с методами.

1 Ответ

0 голосов
/ 25 февраля 2020

Вероятно, лучшим способом было бы посмотреть, как Mediatr реализует шаблон, поскольку это самая популярная библиотека C# для шаблона Mediator / в сообщениях приложений.

https://github.com/jbogard/MediatR/blob/master/src/MediatR/Mediator.cs

Короче говоря, он содержит список объектов-оболочек «NotificationHandlerWrapperImpl». Но он удерживает их в списке объектов (так что вы можете обойти действия Action vs Action vs Action Casting).

private static readonly ConcurrentDictionary<Type, object> _requestHandlers = new ConcurrentDictionary<Type, object>();

Реальная реализация этой оболочки довольно проста: https://github.com/jbogard/MediatR/blob/e8833143c0742bdf72a6c6f104ef1dfadb59bf42/src/MediatR/Internal/NotificationHandlerWrapper.cs

Она в основном использует шаблон локатора службы для получения экземпляров IHandler:

var handlers = serviceFactory
    .GetInstances<INotificationHandler<TNotification>>()
    .Select(x => new Func<INotification, CancellationToken, Task>((theNotification, theToken) => x.Handle((TNotification)theNotification, theToken)));

Mediatr на самом деле довольно прост, и я настоятельно рекомендую скачать исходный код, если вы хотите выбирать и подталкивать его к созданию собственного. В противном случае, просто используйте сам Mediatr, так как в большинстве случаев этого будет достаточно, и вам не нужно наматывать свой собственный! Краткое руководство по настройке и запуску здесь: https://dotnetcoretutorials.com/2019/04/30/the-mediator-pattern-part-3-mediatr-library/

...