3

我在单元测试中尝试了 NBuilder。一个优秀的图书馆。但是,我无法解释以下类和接口的结构。

  • FizzWare.NBuilder命名空间中:

    • ISingleObjectBuilder
    • SingleObjectBuilderExtensions
  • FizzWare.NBuilder.Implementation

    • 对象生成器`
    • ObjectBuilder
  • SingleObjectBuilderExtensions只是IObjectBuilder.

  • 客户端代码通常应该使用一个名为的类Builder,它有一个静态方法,可以为您提供ISingleObjectBuilder. 您永远不需要在客户端代码中实例化任何类。

现在,我不明白SingleObjectBuilderExtensions. 它会给设计带来任何好处吗?ISingleObjectBuilder当两个接口在同一个命名空间中时,为什么不直接使用方法。

4

2 回答 2

8

ISingleObjectBuilder是一个接口;接口不能提供实现。这意味着每个实现ISingleObjectBuilder都需要提供实现。

然而,在许多情况下,一个方法有一个预定义的行为,并且只需要访问接口的其他成员(即只是 的成员ISingleObjectBuilder),所以让每个实现都提供这个并没有什么好处。

此外,向现有接口添加更多成员并不是一个好主意,因为这将是所有现有实现的重大更改。

扩展方法解决了这两个问题:

  1. 扩展方法将适用于所有实现ISingleObjectBuilder
  2. 它不会更改现有 API,因此所有现有实现将继续有效

将它放在同一个命名空间中只会使其方便。很有可能,任何 using 的代码ISingleObjectBuilder都已经有一个using导入该命名空间的指令;因此,大多数代码只需在 IDE 中按下即可在 IDE 中看到扩展方法.

添加一个具体示例,LINQ-to-Objects 适用于IEnumerable<T>. 有很多实现IEnumerable<T>。如果他们每个人都必须编写自己的First(...), FirstOrDefault(...), Any(...), Select(...)etc 方法,那将是一个巨大的负担 - 机器人不会提供任何好处,因为在大多数情况下实现几乎相同。此外,回顾性地将其安装到界面上将是灾难性的。

附带说明:方法的每个类型版本始终优先于扩展方法,因此如果(在 LINQ-to-Objects 的情况下)您有一个实现IEnumerable<T>(对于 some T)的类型,并且该类型有一个.First()实例方法, 然后:

YourType foo = ...
var first = foo.First();

将使用您的版本,而不是扩展方法。

于 2012-08-06T07:28:17.067 回答
2

扩展方法只是语法糖。它们是正常的静态方法,可以处理它们“扩展”公开的类的公共数据。

这些扩展方法似乎不需要使用私有字段,它还使您能够拥有接口而不是抽象类。并且每个人都知道接口是比抽象类更好的选择。

两者都在同一个命名空间中的原因是为了避免仅仅为了使用扩展方法而声明新的命名空间。有多少次这种情况发生在您身上,您尝试使用 LINQ 只是发现智能感知中没有方法或代码没有编译。没有包含 System.Linq 命名空间的原因。

于 2012-08-06T07:24:33.897 回答