3

我有一个ICommandICommandHandler<TCommand>接口,需要注入工厂:

public class CommandProcessor
{
    private readonly Func<Type, ICommandHandler<ICommand>> _handler;

    public CommandProcessor(Func<Type, ICommandHandler<ICommand>> handler)
    {
        _handler = handler;
    }
}

具有执行以下操作的能力:

public void Process(ICommand command)
{
    var handler = _handler(command.GetType());

    if (handler != null)
    {
        handler.Handle(command);
    }

    throw ...
}

我试图注册工厂:

    builder.Register<Func<Type, ICommandHandler<ICommand>>>(context => type =>
        {
            var handlerType = context.Resolve(type);
            return (ICommandHandler<ICommand>) handlerType;
        });

但得到以下异常:

请求的服务“QVocado.Commands.Information.PostProblemCommentCommand”尚未注册。为避免此异常,请注册组件以提供服务,使用 IsRegistered() 检查服务注册,或使用 ResolveOptional() 方法解决可选依赖项。

4

1 回答 1

1

在我看来,您CommandProcessor只是系统中无用的抽象。与其让消费者依赖于CommandProcessor,不如让他们直接依赖于一个或多个封闭版本的ICommandHandler<TCommand>接口。这可以优雅地解决您的问题,因为 Autofac 可以为您解决这些依赖关系。此外,这可以防止将对象/依赖关系图分解为子图(当您使用工厂时会发生这种情况),这使得验证您的 DI 配置变得更加容易。

也许您引入CommandProcessor抽象的原因是因为您必须将许多ICommandHandler<TCommand>依赖项注入消费者。在这种情况下,您可能违反了单一职责原则,这会导致类难以维护和测试。

删除CommandProcessor也消除了ICommand在每个命令消息上实现的需要。

请注意,您注册的委托不解析命令处理程序,而只是一个命令。您将创建用于执行此操作的ICommandHandler<TCommand>接口的封闭通用版本。MakeGenericType这是正确的实现:

builder.Register<Func<Type, ICommandHandler<ICommand>>>(
    context => commandType =>
    {
        var handlerType = typeof(ICommandHandler<>)
            .MakeGenericType(commandType);
        var handler = context.Resolve(handlerType);
        return (ICommandHandler<ICommand>)handler;
    });
于 2013-04-18T12:34:20.373 回答