c# - Autofac 解决 CQRS CommandDispatcher 中的依赖关系

标签 c# .net dependency-injection autofac cqrs

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

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

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
    }

}

这是接口(interface) ICommandDipatcher。它向其处理程序发送命令。

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

这是 ICommandDispatcher 的默认实现,主要问题是通过 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);
    }
}

在这种情况下,通过 Autofac 按命令类型解析 ICommandHanler 实现的最佳方法是什么?

谢谢!

最佳答案

使用 Autofac,您需要注入(inject) IComponentContext进入调度员。这样您就可以回调到容器中以解析所需的命令处理程序:

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

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

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

不过有两个注意事项。首先,您可能定义了 ICommandHandler<T>作为逆变(使用 in 关键字)因为 Resharper 是这么说的,但这对于命令处理程序来说是个坏主意。命令和命令处理程序之间始终存在一对一的映射,但定义 in关键字,表示可以有多个实现。

其次,在我看来,拥有命令调度程序不是一个好主意,因为这会掩盖命令处理程序的消费类具有太多依赖项的事实,这表明违反了单一职责原则。此外,使用这样的调度程序会推迟对象图的一部分(命令处理程序的一部分)的创建,直到命令实际执行(与解析消费者时相反)。这使得验证容器的配置变得更加困难。当命令处理程序被直接注入(inject)时,您肯定知道当您的配置中的根类型可以被解析时,整个对象图就可以被解析。很容易定义一个命令却忘记创建相应的命令处理程序,因此您需要为此添加单元测试以检查每个命令是否有相应的处理程序。如果您一起删除调度程序,您可以避免编写此类测试。

关于c# - Autofac 解决 CQRS CommandDispatcher 中的依赖关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26595829/

相关文章:

c# - 在 C# 中加速矩阵加法

C# 记录类型 : Equality comparisons between record sub-classes

c# - foreach 循环中的 DeleteObject()

c# - 对名称值集合进行排序

c# - PostgreSQL 相当于 IF @@ROWCOUNT=0 INSERT INTO

用于验证字母数字字符、所有国际字符(日语、中文、俄语等)的 JavaScript 正则表达式

dependency-injection - 如何使用依赖注入(inject)扩展组件?

java - 在有/没有抽象绑定(bind)的情况下使用 CDI 和 Jersey 的依赖注入(inject)

php - 如何为单独的包定义可选依赖项?

c# - 为什么我的 StringReader 比 .NET StringReader 慢 50us?