【问题标题】:Code contracts and interface implementations - What are some reasons for the 1-1 relationship代码契约和接口实现——1-1关系有哪些原因
【发布时间】:2012-07-30 20:11:57
【问题描述】:

了解有关代码合约的更多信息,它们似乎是我想在我的项目中使用的东西。

鉴于我构建 Web 服务层(从 MVC 控制器访问的服务层的抽象)的方式,我发现自己想知道为什么不能为接口实现的各种排列指定不同的合同.

具体来说,我对在给定通用接口方法的情况下只能以 1-1 方式指定合同的原因感兴趣。

以下是我的代码结构示例,我的目标是确定我希望如何使用代码协定。我相信有更多经验的人能够将我推向正确的方向。

我正在使用 CQRS 风格的方法:

public interface IQuery<in TInput input,out TOutput output>
{
     TOutput Invoke(TInput request)
}

public interface IGetSomeUnicornsFromAMagicalLand : 
                                             IQuery<int, IEnumerable<Unicorn>>{}

 // Implementation
public class GetSomeUnicornsFromMagicLand : IGetSomeUnicornsFromAMagicalLand
{
    public IEnumerable<Unicorn> Invoke(int numberOfUnicornsToReturn)
    {
       // Here I'd like to specify some preconditions on the input, 
       // specific to type int

       return _wizardry
                 .GetMagicCreature<Unicorn>(numberOfUnicornsToReturn)
                 .DoMagicalConversionToEnumerable()
    }

}

鉴于这种情况,希望在实现级别而不是在设计用于在接口上应用合同的抽象类(作为一种通用机制)中指定合同似乎是合理的。

  • 无法执行此操作的一些原因是什么?
  • 还有其他方法可以解决这个问题吗?
  • 如果我想使用代码契约,这不是一个好的结构吗?

【问题讨论】:

  • 你的意思是服务合同还是代码合同?它们是非常不同的东西。 WCF 和你的例子让我想到了服务合同
  • 我指的是System.Diagnostics.Contracts

标签: c# code-contracts


【解决方案1】:

鉴于Liskov Substitution Principle,总的来说,我认为在接口级别指定这些合同确实更有意义。

LSP 基本上说抽象概念的每个实现都应该是可互换的,而抽象概念的用户不必知道它们之间的区别。换句话说,你的代码不应该因为你切换到某个接口的另一个实现而开始中断。

通过对输入参数施加特定于实现的附加要求,您可以有效地将调用代码(在您的情况下最有可能是处理IQuery 的一般概念的框架级代码)耦合到特定实现。

对于您的具体情况,推理可能适用也可能不适用(这就是为什么它是一个原则,它不是一成不变的),但显然像代码合同这样的一般框架只能考虑一般原则:-)

编辑:在考虑了更多之后,在我看来派生接口可能是“真正的”接口,而不是通用的IQuery&lt;TInput, TOutput&gt;。通用基础接口似乎更像是一个“实现细节”,您确实不能对这个通用基础接口做出任何有意义的假设(合同)。只有在具体的层面上,你才能对这些输入和输出参数做出任何有意义的推理。

也许我们需要在 C# 中使用 C++ 的私有继承(或实现继承)来对消费者“隐藏”这个接口。 Read this excellent answer to a related question。它还谈到 Liskov 可替代性在这种情况下是“谎言”,我倾向于同意。

【讨论】:

  • 感谢您的回复@jeroenh。我不断回到的一个问题是确定如何将代码合同与泛型一起使用。如果我传入一个 int,我想要一个与传入字符串或自定义类型不同的联系人。您如何在接口级别处理?
  • @JamieDixon 似乎是我的编辑。将合约放在通用基础接口上可能真的没有意义。
猜你喜欢
  • 2013-08-18
  • 2015-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-19
  • 1970-01-01
相关资源
最近更新 更多