繁体   English   中英

我如何结合这两个通用接口-ICommand和ICommand的命令处理程序<TResult>

[英]How can I combine these two generic interfaces - command handlers for ICommand and ICommand<TResult>

在我的项目中,我有两种类型的命令:

  • 没有结果的命令(ICommand)
  • 带结果的命令(ICommand)

现在,我有了以下命令处理程序:

public interface ICommandHandler<in TCommand> where TCommand : class, ICommand {
    Task Handle(TCommand command, CancellationToken cancellationToken = default(CancellationToken));
}

public interface ICommandHandler<in TCommand, TResult> where TCommand : class, ICommand<TResult> {
    Task<TResult> Handle(TCommand command, CancellationToken cancellationToken = default(CancellationToken));
}

问题:是否可以为两种类型的命令创建单个ICommandHandler接口?

在回答之前-这是一个问题:为什么需要一个界面同时包含两个界面? 它们是两个不同的接口。 如果将它们分开,则一个类可以实现一个,另一个或两者。 如果您已经具有将两个接口合并为一个接口的灵活性,那么将它们组合可能没有任何好处。

这样想:类更可能仅依赖一个接口或另一个接口。 它要么调用不返回结果的方法,要么返回不返回结果的方法。 (我不能肯定地说,只是它更有可能。)将接口分开可以使类仅依赖其所需的接口,而仅依赖于接口隔离原则。 即使该类实现了两个接口,也是如此。

合并也会使您有点混乱,因为如果您要在类级别声明所有泛型类型参数,那么您实际上有三个泛型参数: TCommandTResult和另一个用于表示ICommand<TResult>

您可以使用继承,以便至少没有 TResult的处理程序保持独立:

public interface ICommandHandler<in TCommand>
    where TCommand : class, ICommand
{
    Task Execute(TCommand command, CancellationToken cancellationToken = default(CancellationToken));
}

public interface ICommandHandler<in TCommand, TResult, in TCommandWithResult> : ICommandHandler<TCommand>
    where TCommand : class, ICommand
    where TCommandWithResult : ICommand<TResult>
{
    Task<TResult> GetResult(TCommandWithResult command, CancellationToken cancellationToken = default(CancellationToken));
}

或者,如果您真的想将它们放在一个界面中,则可以这样做:

public interface ICombinedCommandHandler<in TCommand, TResult, in TCommandWithResult>
    where TCommand : class, ICommand
    where TCommandWithResult : ICommand<TResult>
{
    Task Execute(TCommand command, CancellationToken cancellationToken = default(CancellationToken));
    Task<TResult> GetResult(TCommandWithResult command, CancellationToken cancellationToken = default(CancellationToken));
}

如果ICommand<TResult>ICommand继承,则可以消除第3个通用参数。 也许我的想法比某些人更简单,但这接近了我所谓的“疯狂兔子洞”的边缘。 在某个时候,我开始认真地想知道我为什么要这样做,而且通常没有很好的理由,或者我不记得了。

public interface ICommand { }
public interface ICommand<TResult> : ICommand { }

public interface ICommandHandler<in TCommand>
    where TCommand : class, ICommand
{
    Task Execute(TCommand command, CancellationToken cancellationToken = default(CancellationToken));
}

public interface ICommandHandler<in TCommand, TResult> : ICommandHandler<TCommand>
    where TCommand : class, ICommand<TResult>
{
    Task<TResult> GetResult(TCommand command, CancellationToken cancellationToken = default(CancellationToken));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM