自动填充在CQRS CommandDispatcher中解析依赖关系 [英] Autofac resolve dependency in CQRS CommandDispatcher

查看:193
本文介绍了自动填充在CQRS CommandDispatcher中解析依赖关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一个简单的CQRS应用程序示例。

I'm trying to implement a simple CQRS-application example.

这是我的命令部分的结构:

This is structure of my "Command" part:

public interface ICommand
{
}

//base interface for command handlers
interface ICommandHandler<in TCommand> where TCommand: ICommand
{
    void Execute(TCommand command);
}

// example of the command
public class SimpleCommand: ICommand 
{
   //some properties
}

// example of the SimpleCommand command handler
public class SimpleCommandHandler: ICommandHandler<SimpleCommand>
{
    public void Execute(SimpleCommand command)
    {
       //some logic
    }

}

这是界面 ICommandDipatcher 。它向其处理程序发送一个命令。

This is interface ICommandDipatcher. It dispatches a command to its handler.

public interface ICommandDispatcher
{
    void Dispatch<TCommand>(TCommand command) where TCommand : ICommand;
}

这是 ICommandDispatcher 主要问题是通过 Autofac 命令类型获取必要的命令处理程序。

This is a default implementation of ICommandDispatcherand the main problem is getting the necessary command handler by the type of command via Autofac.

public class DefaultCommandDispatcher : ICommandDispatcher
{
    public void Dispatch<TCommand>(TCommand command) where TCommand : ICommand
    {
        //How to resolve/get object of the neseccary command handler 
        //by the type of command (TCommand)
        handler.Execute(command);
    }
}

解决 ICommandHanler 根据这种情况通过 Autofac 命令的类型

What is the best way to resolve implementation of ICommandHanler by the type of command in that case via Autofac?

谢谢!

推荐答案

使用Autofac,您需要将 IComponentContext 注入调度程序。这样你可以调用回到容器来解析所需的命令处理程序:

With Autofac, you need to inject the IComponentContext into the dispatcher. This way you can call back into the container to resolve the required command handler:

public class AutofacCommandDispatcher : ICommandDispatcher
{
    private readonly IComponentContext context;

    public AutofacCommandDispatcher(IComponentContext context)
    {
        this.context = context;
    }

    public void Dispatch<TCommand>(TCommand command)
    {
        var handler = this.context.Resolve<ICommandHandler<TCommand>>();

        void handler.Execute(command);
    }
}

您可以注册 AutofacCommandDispatcher 如下:

builder.RegisterType<AutofacCommandDispatcher>().As<ICommandDispatcher>();

您可以一次性注册所有的命令处理程序,如下所示:

And you can register all your command handlers in one go as follows:

builder.RegisterAssemblyTypes(myAssembly)
    .AsClosedTypesOf(typeof(ICommandHandler<>));

首先,您可能将 ICommandHandler< T> 定义为逆向(在关键字中的),因为Resharper说,但这对于命令处理程序来说是一个坏主意。在命令和命令处理程序之间始终存在一对一的映射,但是在关键字中定义可以通信多个实现。

Two notes though. First of all, you probably defined the ICommandHandler<T> as contravariant (with the in keyword) because Resharper said so, but this is a bad idea for command handlers. There is always a one-to-one mapping between a command and command handler, but defining the in keyword, communicates that there can be multiple implementations.

第二,在我看来,使用命令调度程序是一个坏主意,因为这可以隐藏消息类的命令处理程序具有太多的依赖性,这表示违反了单一责任原则。此外,使用这样的调度器推迟创建对象图的一部分(命令处理程序的一部分),直到命令实际执行(与消费者解析时相反)。这使得更难验证容器的配置。当直接注入命令处理程序时,您可以确定当您的配置中的根类型可以解决时,可以解决整个对象图。很容易定义一个命令,但忘记创建相应的命令处理程序,因此您需要添加单元测试来检查每个命令是否具有相应的处理程序。如果您将调度员全部删除,您可以免除自己编写这样的测试。

Second, in my opinion, having a command dispatcher is a bad idea, because this can hide the fact that the consuming classes of command handlers have too many dependencies, which is an indication of a violation of the Single Responsibility Principle. Further more, using such a dispatcher postpones creation of part of the object graph (the part of the command handler) until the command is actually executed (opposed to when the consumer is resolved). This makes it harder to verify the container's configuration. When command handlers are injected directly, you know for sure that the whole object graph can be resolved when the root types in your configuration can be resolved. It's easy to define a command but forget to create the corresponding command handler, so you will need to add unit tests for this to check if each command has a corresponding handler. You can save yourself from having to write such test if you remove the dispatcher all together.

这篇关于自动填充在CQRS CommandDispatcher中解析依赖关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆