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 : IComman
和ConcreteCommandHandler : ICommandHandler
使用这样的RegisterType方法:
builder.RegisterType() .As>();
然后注入你的处理程序:
private ICommandHandler concreteCommandHandler;
另请参阅自动assembly类型注册 Autofacfunction。
如果您想通过ICommand
实现解决ICommandHandler
,那么工厂注册可以提供帮助。 注册Func
或定义将解析适当命令处理程序的特殊类。