设计模式-用C#3编写流畅接口的技巧

我正在寻找一些有关C#中流畅接口的好技巧。 我本人只是在学习它,但是渴望听到别人在我正在阅读的文章之外的想法。 我特别追求:

  1. 什么时候流利太多?
  2. 是否有流利的模式?
  3. C#中的什么使流利的界面更流利(例如扩展方法)
  4. 复杂的流利界面仍然是流利的吗?
  5. 重构以达到流畅的界面或重构现有的流畅界面
  6. 您曾经合作过或可以推荐的好例子吗?

如果您可以发表一个小贴士或想法,或每篇文章发表任何内容。 我也想看看他们如何获得投票。

先感谢您。

8个解决方案
27 votes

作为使用流畅接口的消费者,我遇到的最大挑战是,它们中的大多数并不是真正的流畅接口,而是它们确实是我倾向于称之为“清晰接口”的实例。

流利的界面意味着其主要目标是使其易于说话,而清晰的界面则意味着其主要目标是易于阅读。 多数流利的接口往往很难用它们编写代码,相反,其他人后来很难阅读。

Assert().That().This(actual).Is().Equal().To(expected).
    Except().If(x => x.GreaterThan(10));

...比实际编写代码要容易阅读得多!

sbohlen answered 2020-08-01T15:53:22Z
18 votes

在第四点;

是的,我认为复杂的流畅界面仍然可以流畅。

我认为流畅的界面有些妥协。 (尽管是一个好人!)已经有很多关于使用自然语言进行编程的研究,并且自然语言还不够精确,无法表达程序。

流利的接口的构造使其可以像编程语言一样编写,只允许使用自然语言表达的内容的一小部分,但它们却像自然语言一样读取。

例如,如果您查看犀牛模型,与普通库相比,书写部分就比较复杂。 由于界面流畅,我花了更长的时间学习,但这使代码更易于阅读。 因为程序通常只编写一次,并且读取多次,所以这是一个很好的权衡。

因此,让我的观点有一点点。 编写复杂但易于阅读的流畅界面仍然可以流畅。

Mendelt answered 2020-08-01T15:52:52Z
11 votes

在将继承与流利的接口一起使用时,您会遇到麻烦,因为使用多态方法会中断您的调用链,并且您绝对不希望通过在不需要它们的地方使用丑陋的转换和寄生来使接口不流利。我写了一篇有关模式的文章,为您提供了一种使用通用构建器和具有通用约束的通用扩展方法的解决方法:[http://liviutrifoi.wordpress.com/2009/02/16/fluent-interfaces-constraints-at-compile-time/]

Csaba Toth answered 2020-08-01T15:53:43Z
8 votes

Moq隐藏了未发布的方法,例如equals,ToString等,以使其流畅的界面更易于使用。

隐藏系统对象是一篇文章,解释了这样做的好处。

Finglas answered 2020-08-01T15:54:08Z
7 votes

关于第二个和第三个问题;

我注意到的三种流利模式

第一个使用using语句(C#2.0)在特定上下文中运行代码,例如:

using(var transaction = new Transaction())
{
  // ..
  // ..
}

这使用Transaction的构造函数和处理程序来设置事务,然后在此上下文中运行代码。

第二个功能几乎相同,但使用lambda的功能,例如在Rhino Mocks中使用很多。

(new Transaction()).Run( () => mycode(); );

最有名的流利接口是使用返回类型链接方法调用。 通常,方法返回此值,因此您可以在同一对象上链接调用。 但是您还可以根据调用的方法返回不同的对象来更改上下文。 如果您有一个只能在事务中运行的对象(对不起,无法想到其他示例),可以给它提供一个StartTransaction方法,该方法返回一个初始化的事务,您可以在其中以伪代码运行调用run和stoptransaction:

class Runner
{
  Transaction StartTransaction()
  {
    return new Transaction(this);
  }
}

class Transaction
{
  Transaction Run()
  Transaction StopTransaction()
}

通话看起来像什么

var runner = new Runner();
runner
  .StartTransaction()
  .Run()
  .StopTransaction();

当然,您需要添加各种错误处理等。

Mendelt answered 2020-08-01T15:54:59Z
7 votes

我也刚开始学习如何为工作中的小型应用程序编写流畅的界面。 我四处询问并进行了一些研究,发现编写流畅接口的一种好方法是使用“构建器模式”,在此处了解更多信息。

本质上,这就是我开始采矿的方式:

public class Coffee
{
    private bool _cream;
    private int _ounces;

    public Coffee Make { get new Coffee(); }

    public Coffee WithCream()
    {
        _cream = true;
        return this;
    }

    public Coffee WithOuncesToServe(int ounces)
    {
        _ounces = ounces;
        return this;
    }
}

这是我在流利的接口中实现闭包的类似问题的交叉帖子。

sam answered 2020-08-01T15:55:27Z
4 votes

一件事是,您必须考虑英语语法的形态,并确保没有在下面引入未记录的顺序耦合。

// Snarky employees get a raise.
employees.WhereSnarky().GiveRaise();

// Depending on implementation, everyone may get a raise.
employees.GiveRaise().WhereSnarky();
An00bus answered 2020-08-01T15:55:52Z
2 votes

以前的某个时候,我对您现在遇到的疑问也一样。 我已经做了一些研究,现在我正在写一些文章来帮助这些话题。

在我的博客上检查:

C#第1部分中的Fluent接口设计准则

在以下帖子中,我将介绍您提到的所有要点。

最好的祝福安德烈·维安娜(AndréVianna)

Andre Vianna answered 2020-08-01T15:56:29Z
translate from https://stackoverflow.com:/questions/224730/tips-for-writing-fluent-interfaces-in-c-sharp-3