[英]Autofac resolve dependency in CQRS CommandDispatcher
我正在嘗試實現一個簡單的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
}
}
這是接口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,您需要將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
關鍵字,表明可以有多個實現。
其次,在我看來,擁有一個命令調度程序是一個壞主意,因為這可以隱藏消耗類命令處理程序具有太多依賴關系這一事實,這表明違反了單一責任原則。 此外,使用這樣的調度程序推遲創建對象圖的一部分(命令處理程序的一部分),直到命令被實際執行(與消費者被解析時相反)。 這使得驗證容器配置變得更加困難。 直接注入命令處理程序時,您確定可以在解析配置中的根類型時解析整個對象圖。 定義命令很容易但忘記創建相應的命令處理程序,因此您需要為此添加單元測試以檢查每個命令是否具有相應的處理程序。 如果您同時刪除調度程序,則可以避免編寫此類測試。
假設你有ConcreteCommand : IComman
和ConcreteCommandHandler : ICommandHandler<ConcreteCommand>
使用這樣的RegisterType方法:
builder.RegisterType<ConcreteCommandHandler>()
.As<ICommandHandler<ConcreteCommand>>();
然后注入你的處理程序:
private ICommandHandler<ConcreteCommand> concreteCommandHandler;
另請參閱自動裝配類型注冊 Autofac功能。
如果您想通過ICommand
實現解決ICommandHandler
,那么工廠注冊可以提供幫助。 注冊Func<Type, ICommandHandler>
或定義將解析適當命令處理程序的特殊類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.