我一直在使用SimpleInjector,我正在尝试正确注册所有命令处理程序。
这是我的代码:
public interface ICommand {}
public interface ICommandDispatcher
{
void Execute(ICommand command);
}
public class CommandDispatcher : ICommandDispatcher
{
private readonly Container container;
public CommandDispatcher(Container container)
{
this.container = container;
}
public void Execute(ICommand command)
{
var handlerType = typeof(ICommandHandler<>).MakeGenericType(command.GetType());
dynamic handler = container.GetInstance(handlerType);
handler.Handle((dynamic)command);
}
}
public interface ICommandHandler<in TParameter> where TParameter : ICommand
{
void Handle(TParameter command);
}
public class UserCommandsHandler : ICommandHandler<CreateUser>
{
public void Handle(CreateUser message)
{
var user = new User(message.Email);
/* logic here */
}
}
public class CreateUser : ICommand
{
public readonly string Email;
public CreateUser(string email)
{
Email = email;
}
}
var assemblies = new[] { typeof(ICommandHandler<>).Assembly };
var container = new SimpleInjector.Container();
container.RegisterCollection(typeof(ICommandHandler<>), assemblies);
container.RegisterSingleton<ICommandDispatcher>(new CommandDispatcher(container));
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
public class HomeController : Controller
{
private readonly ICommandDispatcher _commandDispatcher;
public HomeController(ICommandDispatcher commandDispatcher)
{
_commandDispatcher = commandDispatcher;
}
public ActionResult Index()
{
var command = new CreateUser("email@example.com");
_commandDispatcher.Execute(command);
return Content("It works");
}
}
在CQRS.cs
dynamic handler = container.GetInstance(handlerType);
我明白了:
无法找到
ICommandHandler<CreateUser>
类型的注册。 但是,有IEnumerable<ICommandHandler<CreateUser>>
的注册; 您的意思是致电GetAllInstances<ICommandHandler<CreateUser>>()
还是依赖IEnumerable<ICommandHandler<CreateUser>>
?
答案 0 :(得分:4)
Simple Injector API明确separates between registrations for collections和一对一映射。在撰写根目录中,您正在进行以下注册:
container.RegisterCollection(typeof(ICommandHandler<>),
new[] { typeof(ICommandHandler<>).Assembly });
RegisterCollection
州的API文档:
注册一组serviceTypes,每次枚举已解析的serviceType集合时,其实例将被懒惰地解析。基础集合是一个流,它将根据其特定的注册生活方式返回单个实例,每次调用
IEnumerator<T>.Current
。类型在集合中出现的顺序与项目的注册顺序完全相同,即已解析的集合具有确定性。
换句话说,您通过请求IEnumerable<ICommandHandler<T>>
允许将命令处理程序解析为集合。
但是,在CommandDispatcher
,您可以通过致电ICommandHandler<T>
来申请一个container.GetInstance(handlerType)
。由于ICommandHandler<T>
没有一对一的映射,Simple Injector通过抛出来告知你这个:
无法找到
ICommandHandler<CreateUser>
类型的注册。 但是,有IEnumerable<ICommandHandler<CreateUser>>
的注册; 您的意思是致电GetAllInstances<ICommandHandler<CreateUser>>()
还是依赖IEnumerable<ICommandHandler<CreateUser>>
?
要解决此问题,有两种选择:
CommandDispatcher
来解析GetAllInstances(Type)
中的一组处理程序。由于命令与其处理程序之间始终存在一对一的映射(意味着:每个命令只有一个处理程序),因此选项1是最明显的解决方案。因此,请将注册更改为以下内容:
// Use 'Register' instead of 'RegisterCollection'.
container.Register(typeof(ICommandHandler<>),
new[] { typeof(ICommandHandler<>).Assembly });