没有使用SimpleInjector APIv3注册类型ICommandHandler

问题描述 投票:1回答:1

我一直在使用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 protected]");
        _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>>

asp.net-mvc dependency-injection cqrs simple-injector
1个回答
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. 您可以通过调用CommandDispatcher来解析GetAllInstances(Type)中的一组处理程序。

由于命令与其处理程序之间始终存在一对一映射(意味着:每个命令只有一个处理程序),因此选项1是最明显的解决方案。因此,请将注册更改为以下内容:

// Use 'Register' instead of 'RegisterCollection'.
container.Register(typeof(ICommandHandler<>), 
    new[] { typeof(ICommandHandler<>).Assembly });
© www.soinside.com 2019 - 2024. All rights reserved.