没有使用SimpleInjector APIv3注册类型ICommandHandler

时间:2015-12-04 15:14:45

标签: asp.net-mvc dependency-injection cqrs simple-injector

我一直在使用SimpleInjector,我正在尝试正确注册所有命令处理程序。

这是我的代码:

CQRS.cs

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

Handler.cs

public class UserCommandsHandler : ICommandHandler<CreateUser>
{
    public void Handle(CreateUser message)
    {
        var user = new User(message.Email);
        /* logic here */
    }
}

Command.cs

public class CreateUser : ICommand
{
    public readonly string Email;

    public CreateUser(string email)
    {
        Email = email;
    }       
}

的Global.asax.cs

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

HomeController.cs

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>>

1 个答案:

答案 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>>

要解决此问题,有两种选择:

  1. 使用一对一映射或
  2. 注册处理程序
  3. 您可以通过调用CommandDispatcher来解析GetAllInstances(Type)中的一组处理程序。
  4. 由于命令与其处理程序之间始终存在一对一的映射(意味着:每个命令只有一个处理程序),因此选项1是最明显的解决方案。因此,请将注册更改为以下内容:

    // Use 'Register' instead of 'RegisterCollection'.
    container.Register(typeof(ICommandHandler<>), 
        new[] { typeof(ICommandHandler<>).Assembly });