Autofac解决CQRS CommandDispatcher中的依赖关系

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

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

public interface ICommand { } //base interface for command handlers interface ICommandHandler 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 { public void Execute(SimpleCommand command) { //some logic } } 

这是接口ICommandDipatcher 。 它将命令分派给其处理程序。

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

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

 public class DefaultCommandDispatcher : ICommandDispatcher { public void Dispatch(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,您需要将IComponentContext注入调度程序。 这样您就可以回调容器来解析所需的命令处理程序:

 public class AutofacCommandDispatcher : ICommandDispatcher { private readonly IComponentContext context; public AutofacCommandDispatcher(IComponentContext context) { this.context = context; } public void Dispatch(TCommand command) { var handler = this.context.Resolve>(); void handler.Execute(command); } } 

您可以按如下方式注册AutofacCommandDispatcher

 builder.RegisterType().As(); 

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

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

虽然有两个音符。 首先,您可能将ICommandHandler定义为逆变(使用in关键字),因为Resharper这样说,但这对于命令处理程序来说是个坏主意。 命令和命令处理程序之间总是存在一对一的映射,但定义了in关键字,表明可以有多个实现。

其次,在我看来,拥有一个命令调度程序是一个坏主意,因为这可以隐藏消耗类命令处理程序具有太多依赖关系这一事实,这表明违反了单一责任原则。 此外,使用这样的调度程序推迟创建对象图的一部分(命令处理程序的一部分),直到命令被实际执行(与消费者被解析时相反)。 这使得更难validation容器的配置。 直接注入命令处理程序时,您确定可以在解析配置中的根类型时解析整个对象图。 定义命令很容易但忘记创建相应的命令处理程序,因此您需要为此添加unit testing以检查每个命令是否具有相应的处理程序。 如果您同时删除调度程序,则可以避免编写此类测试。

假设你有ConcreteCommand : ICommanConcreteCommandHandler : ICommandHandler使用这样的RegisterType方法:

 builder.RegisterType() .As>(); 

然后注入你的处理程序:

 private ICommandHandler concreteCommandHandler; 

另请参阅自动assembly类型注册 Autofacfunction。

如果您想通过ICommand实现解决ICommandHandler ,那么工厂注册可以提供帮助。 注册Func或定义将解析适当命令处理程序的特殊类。