【问题标题】:C# Generics / ICommandHandler/ICommand designC# 泛型/ICommandHandler/ICommand 设计
【发布时间】:2013-05-30 02:15:16
【问题描述】:

我必须设计一个 Command/CommandHandler 模块,并且正在为设计的细节而苦苦挣扎。

我创建了一个(空)接口:

public interface ICommand {}

由各种命令实现,

例如

public interface TestCommand : ICommand {}

一个(或多个)CommandHandler 可以注册ICommand 的特定实现。为了避免不断转换,我构建了一个接口:

public interface ICommandHandler<in TCommand>
       where TCommand : ICommand
{
    void Handle(TCommand command);
}

到目前为止一切顺利...命令调度系统是个麻烦事:命令处理程序应该由 Autofac(或任何其他 DI 系统)注入,例如:

public CommandDispatcher (IEnumerable<ICommandHandler<ICommand>> commandHandlers)

如您所见,这是不可能的。 ICommandHandler&lt;CommandType1&gt;ICommandHandler&lt;CommandType2&gt; 不是从 ICommandHandler&lt;ICommand&gt; 派生的,因此不能放在同一个 IEnumerable 中。

任何建议如何以一种没有问题的方式设计?

【问题讨论】:

    标签: c# generics covariance


    【解决方案1】:

    通常你会在调用它们之前解决它们。例如,在 Autofac 中

    class CommandDispatcher
    {
        private readonly Autofac.IComponentContext context; // inject this
    
        public void Dispatch<TCommand>(TCommand command)
        {
            var handlers = context.Resolve<IEnumerable<ICommandHandler<TCommand>>>();
            foreach (var handler in handlers)
            {
                handler.Handle(command);
            }
        }
    
        public void ReflectionDispatch(ICommand command)
        {
            Action<CommandDispatcher, ICommand> action = BuildAction(command.GetType());
            // see link below for an idea of how to implement BuildAction
    
            action(this, command);
        }
    }
    

    如果您需要将方法签名更改为Dispatch(ICommand command),请参阅this answer。您应该能够根据自己的情况进行调整。

    【讨论】:

    • 在我看来,到处注入容器是一种非常糟糕的做法。这不应该只发生在顶层吗?
    • 您不会将容器“到处”注入,而只会注入特定的基础设施代码。只要您的代码中有一小部分引用容器,就可以了。有些人会建议定义ICommandDispatcher,然后只在组合根中创建AutofacCommandDispatcher,但我认为这是不必要的间接——如果你切换DI容器,它的工作量是一样的;唯一的好处是,如果您不想在“业务逻辑”程序集中引用 Autofac DLL。
    • 我们已切换到此解决方案以避免不必要的参考 + 我们使用了您链接帖子的反射思想。谢谢。
    猜你喜欢
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-06
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 1970-01-01
    相关资源
    最近更新 更多