简体   繁体   English

C#中介器中的强类型消息处理程序

[英]Strongly-typed Message Handlers in Mediator in C#

I'm currently having a problem implementing a solution for inter-object communication in my current project.我目前在当前项目中实施对象间通信解决方案时遇到问题。 I decided to try out an object like the mediator pattern, where objects communicate with each other using messages via a broadcast to the mediator.我决定尝试像中介者模式这样的对象,在这种模式下,对象通过向中介者广播的方式使用消息相互通信。 The mediator then sends the message to objects that have specifically listened to the message being broadcast.然后,中介将消息发送给专门监听正在广播的消息的对象。

Previous mediator objects I've used relied on holding containers to handlers only handling a base message, forcing listeners to cast the messages before they could handle them.我以前使用过的中介器对象依赖于将容器保存到处理程序只处理基本消息,迫使侦听器在处理消息之前强制转换消息。 I thought I could get by this by having collections of handlers themselves in a keyed collection according to some arbitrary type.我认为我可以通过根据某种任意类型将处理程序本身放在一个键控集合中来解决这个问题。 By doing this, I'm hoping to avoid any kind of casting a listener has to do to respond to a message.通过这样做,我希望避免听众必须做的任何类型的转换来响应消息。

The trouble is, I can't seem to follow how to get an object that allows others to Register for a strongly-typed message to maintain a single collection of different kinds of strongly-typed message handlers.问题是,我似乎无法理解如何获取允许其他人注册强类型消息以维护不同类型强类型消息处理程序的单个集合的对象。

Ideally, I'd like the public-facing interface to look as follows:理想情况下,我希望面向公众的界面如下所示:

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));
     }
}

Is it possible with this design to have the strongly-typed message handling that I want?这种设计是否有可能实现我想要的强类型消息处理? If so, how do I do it?如果是这样,我该怎么做?

Edit - added code to describe how I'd want a sender and receiver object to interact with the methods.编辑 - 添加了代码来描述我希望发送方和接收方对象如何与方法交互。

Probably the best way would be to look at how Mediatr implements the pattern since it's the most popular C# library for the Mediator pattern/in app messaging.可能最好的方法是查看 Mediatr 如何实现该模式,因为它是 Mediator 模式/应用程序消息传递中最流行的 C# 库。

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

In short, it holds a list of wrapper objects of "NotificationHandlerWrapperImpl".简而言之,它包含“NotificationHandlerWrapperImpl”的包装对象列表。 But it holds them in a list of objects (So that you get around Action vs Action vs Action casting issues).但是它将它们保存在一个对象列表中(这样你就可以解决 Action vs Action vs Action 转换问题)。

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

The actual implementation of that wrapper is fairly simple : https://github.com/jbogard/MediatR/blob/e8833143c0742bdf72a6c6f104ef1dfadb59bf42/src/MediatR/Internal/NotificationHandlerWrapper.cs该包装器的实际实现相当简单: https : //github.com/jbogard/MediatR/blob/e8833143c0742bdf72a6c6f104ef1dfadb59bf42/src/MediatR/Internal/NotificationHandlerWrapper.cs

It basically uses the service locator pattern to get instances of IHandler :它基本上使用服务定位器模式来获取 IHandler 的实例:

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

Mediatr is actually quite simple and I highly recommend downloading the source code if you want to pick and prod bits out to build your own. Mediatr 实际上非常简单,如果您想挑选并制作自己的代码,我强烈建议您下载源代码。 Otherwise, just use Mediatr itself as for most cases, it's going to be sufficient and you don't need to roll your own!否则,在大多数情况下,只需使用 Mediatr 本身就足够了,您无需自己动手! Quick guide to getting up and running here : https://dotnetcoretutorials.com/2019/04/30/the-mediator-pattern-part-3-mediatr-library/在此处启动和运行的快速指南: https : //dotnetcoretutorials.com/2019/04/30/the-mediator-pattern-part-3-mediatr-library/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在.Net / C#中,是否为强类型? - In .Net/C#, is null strongly-typed? 易于使用的强类型JSON库用于C# - Easy to use strongly-typed JSON library for C# 在C#中的通用FillDataSet方法中映射强类型数据集? - Mapping strongly-typed DataSets in a generic FillDataSet method in C#? 是否可以将强类型的类作为C#中方法的参数传递? - Is it possible to pass a strongly-typed class as a parameter of a method in C#? 有没有办法定义现有原始类型(如 `string` 或 `int`)的 C# 强类型别名? - Is there a way to define C# strongly-typed aliases of existing primitive types like `string` or `int`? 强类型属性引用多个类,没有通用接口(C#) - Strongly-typed property reference to multiple classes with no common interface (C#) 如何使用c#中的强类型数据库从DataTable AutoIncrementColumn获取自动编号? - How to get an AutoNumber from DataTable AutoIncrementColumn with a Strongly-Typed Database in c#? Objective-C转换为C#:如果字典是强类型的,如何在C#中使用多个类型的.plist? - Objective-C converting to C#: How can I use a .plist with multiple types in C# if Dictionary is strongly-typed? 强类型绑定源过滤器 - Strongly-Typed BindingSource Filter 强类型视图未初始化? - Strongly-typed view not initializing?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM