.net 如何最好地组装一个大型消息处理程序集合

.net 如何最好地组装一个大型消息处理程序集合,.net,inversion-of-control,.net,Inversion Of Control,我正在开始一个消息处理系统的工作,在这个系统中,各种消息将从外部来源到达,需要“处理”。消息对象基本上是DTO 我考虑让消息类生活在它们自己的程序集中,对消息处理系统和外部系统都可用,并让处理程序从通用抽象类继承,大致如下: Messages.dll MessageHandlers.dll 公共抽象类MessageHandler,其中TMessage:Message { 公共无效句柄(TMessage message); } 公共类FooHandler:MessageHandler { 公共无效

我正在开始一个消息处理系统的工作,在这个系统中,各种消息将从外部来源到达,需要“处理”。消息对象基本上是DTO

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

Messages.dll

MessageHandlers.dll

公共抽象类MessageHandler,其中TMessage:Message
{
公共无效句柄(TMessage message);
}
公共类FooHandler:MessageHandler
{
公共无效句柄(FooMessage)
{
...
}
}
现在是问题: 把这些粘在一起的最好方法是什么?我当然可以做一些反思,并编写一个helper函数来根据传入的消息名实例化相应的处理程序,但这不是IoC容器应该擅长的事情吗?有哪一个更适合这份工作?感谢您的意见和指点


谢谢

不久前,我在温莎做了类似的事情。您可以阅读相关内容。

假设容器中的所有组件都已正确配置,这就是处理消息的方式(在本例中,消息是通过队列传输的序列化消息):

var formatter=new BinaryFormatter();
使用(var s=newmemoryStream(message.AsBytes))
{
动态消耗品=格式化程序。反序列化;
var consumerType=typeof(IMessageConsumer).MakeGenericType(consumer.GetType());
动态使用者=this.container.Resolve(consumerType);
消费者。消费品(消耗品);
}

此处提供了完整的示例代码:

因为您需要使用请求/响应消息传递模式,所以可以使用该项目。 这是该模式的一个实现,它是成熟的,在重负载下测试,当然也在使用WCF的过程边界之外

它内置了您提到的所有内容,并与许多流行的IoC容器(Windsor、StructureMap、Unity、Spring.NET、Ninject)集成,因此您不必重新发明轮子,开始关注您的业务逻辑


您可以在Davy Brion的博客上找到非常有用的文章、使用技巧和大量信息。

有几种方法可以注册处理程序。我总是从手动配置一切开始。在您的示例中,它将如下所示:

<!-- language: c# -->
container.Register<IMessageHandler<FooMessage>, FooHandler>();
container.Register<IMessageHandler<BarMessage>, BarHandler>();
// etc
<!-- 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);
    }
}
在DI配置附近,您可以定义
IMessageProcessor
的实现,它可以如下所示:

<!-- language: c# -->
container.Register<IMessageHandler<FooMessage>, FooHandler>();
container.Register<IMessageHandler<BarMessage>, BarHandler>();
// etc
<!-- 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
注入到需要它的类型中。以下是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();
    }
}

[ServiceKnownType(“GetKnownMessageTypes”)]
公共类WCFMessageService
{
专用只读IMessageProcessor;
公共WCFMessageService()
{
此处理器=
Global.Container.GetInstance();
}
[经营合同]
公共作废流程(消息)
{
此.processor.Process(消息);
}
公共静态IEnumerable GetKnown消息类型(
ICustomAttributeProvider(供应商)
{
var known消息类型=
从typeof(Message.Assembly.GetTypes()中的类型
其中typeof(Message).IsAssignableFrom(type)
选择类型;
返回knownMessageTypes.ToArray();
}
}

我希望这能有所帮助。

如果.NET的IObservable还没有这样的功能,我会很惊讶,但我对它不是非常熟悉。@马克,谢谢,你能告诉我这个应用程序中容器的配置位置吗?后台工作容器在这里配置:@Mark,所以真的是这样,对吗?这是否意味着每个处理程序都必须单独配置?我希望摩擦少一点,这是另一个问题。在那个应用程序中,我从未有时间定义基于约定的配置,但这是可能的。@Mark,这是我主要关心的问题之一——问题是如何将其粘合在一起(因此包括注册和解析)。谢谢,但Agatha不是我想要的。对于我的用例来说,这是一种错误的通信模式。下面是相关的配置部分:@Michael,你描述的模式是什么?我读过关于DTO、消息和消息处理程序的文章。是的,您提到的这部分是用于将agatha与wcf一起使用的。
<!-- language: c# -->
public interface IMessageProcessor
{
    void Process(Message message);
}
<!-- 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);
    }
}
<!-- language: c# -->
container.RegisterSingle<IMessageProcessor>(new DIMessageProcessor(container));
<!-- 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();
    }
}