gpt4 book ai didi

.net - 如何最好地组装大量消息处理程序

转载 作者:行者123 更新时间:2023-12-05 00:38:49 26 4
gpt4 key购买 nike

我正着手开发一个消息处理系统,其中各种消息将从外部源到达并需要“处理”。消息对象基本上是 DTO。

我正在考虑让消息类存在于它们自己的程序集中,消息处理系统和外部系统都可用,并让处理程序从通用抽象类继承,大致如下:

Messages.dll

public abstract class Message {}

public class FooMessage : Message
{
...
}

public class BarMessage : Message
{
...
}

MessageHandlers.dll

public abstract class MessageHandler<TMessage> where TMessage : Message
{
public void Handle(TMessage message);
}

public class FooHandler : MessageHandler<FooMessage>
{
public void Handle(FooMessage message)
{
...
}
}

现在是问题:将所有这些粘合在一起的最佳方法是什么?我当然可以做一些反射(reflection)并编写一个辅助函数来根据传入的消息名称实例化适当的处理程序,但这不正是 IoC 容器应该擅长的事情吗?有没有更适合这份工作的人?意见和建议表示赞赏。

谢谢!

最佳答案

有几种方法可以注册您的处理程序。我总是从手动配置一切开始。在您的示例中,它看起来像这样:

<!-- language: c# -->
container.Register<IMessageHandler<FooMessage>, FooHandler>();
container.Register<IMessageHandler<BarMessage>, BarHandler>();
// etc

提示:与其使用抽象基类,不如定义一个 IMessageHandler<T>界面。

一旦应用程序增长,这会变得很麻烦,因此在您的情况下,批量注册应该是可行的方法。所有 DI 容器都有不同的机制。大多数容器开箱即用地支持这一点,而其他容器则不支持。这是使用 Simple Injector 的方法:

<!-- language: c# -->
container.RegisterManyOpenGeneric(typeof(MessageHandler<>),
typeof(MessageHandler<>).Assembly);

这将注册所有实现 MessageHandler<T> 的具体类型和MessageHandler<T>住在同一个集会.同样,这取决于您选择的容器如何编写。

为了处理传入的任意消息,您需要进行一些反射(reflection),但您不应该在应用程序本身中这样做。只需在应用程序中定义一个良好的抽象,并将反射的使用移动到应用程序中您拥有 DI 配置的部分。

例如,您可以定义一个 IMessageProcessor接口(interface),允许处理任何类型的 Message :

<!-- language: c# -->
public interface IMessageProcessor
{
void Process(Message message);
}

在您的 DI 配置附近,您可以定义 IMessageProcessor 的实现,它可能看起来像这样:

<!-- language: c# -->
private class DIMessageProcessor : IMessageProcessor
{
private readonly Container container;

public DIMessageProcessor(Container container)
{
this.container = container;
}

public void Process(Message message)
{
if (message == null) throw new ArgumentNullException("message");

Type messageType = message.GetType();

Type handlerType =
typeof(IMessageHandler<>).MakeGenericType(messageType);

var handler = this.container.GetInstance(handlerType);

handlerType.GetMethod("Handle").Invoke(handler, message);
}
}

将此排除在应用程序之外很重要。您不仅会混合职责,而且会更难添加新行为。例如,考虑防止消息重播(当消息被多次执行时)。将此行为实现为 IMessageProcessor 的装饰器很容易.除此之外,DIMessageProcessor将很容易进行单元测试,或替换为性能更高的新实现(并再次进行单元测试)。

有几种方法可以注册 DIMessageProcessor ,取决于您选择的容器。例如使用简单注入(inject)器:

<!-- language: c# -->
container.RegisterSingle<IMessageProcessor>(new DIMessageProcessor(container));

有了这个,你可以注入(inject) IMessageProcessor进入需要这个的类型。这是 WCF 的示例:

<!-- language: c# -->
[ServiceKnownType("GetKnownMessageTypes")]
public class WCFMessageService
{
private readonly IMessageProcessor processor;

public WCFMessageService()
{
this.processor =
Global.Container.GetInstance<IMessageProcessor>();
}

[OperationContract]
public void Process(Message message)
{
this.processor.Process(message);
}

public static IEnumerable<Type> GetKnownMessageTypes(
ICustomAttributeProvider provider)
{
var knownMessageTypes =
from type in typeof(Message).Assembly.GetTypes()
where typeof(Message).IsAssignableFrom(type)
select type;

return knownMessageTypes.ToArray();
}
}

希望对您有所帮助。

关于.net - 如何最好地组装大量消息处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6069428/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com