我正在寻找一些关于 C# 中流畅接口的好技巧。我自己只是在学习,但很想听听我正在阅读的文章之外的其他人的想法。特别是我追求:
- 什么时候流利太多了?
- 有没有流畅的图案?
- C# 中有什么使流畅的接口更流畅(例如扩展方法)
- 复杂的流畅界面仍然是流畅的界面吗?
- 重构以达到流畅的界面或重构现有的流畅界面
- 您使用过或可以推荐的任何好的例子?
如果您可以发布一个提示或想法,或者每个帖子的任何内容。我也想看看他们是如何被投票的。
先感谢您。
我正在寻找一些关于 C# 中流畅接口的好技巧。我自己只是在学习,但很想听听我正在阅读的文章之外的其他人的想法。特别是我追求:
如果您可以发布一个提示或想法,或者每个帖子的任何内容。我也想看看他们是如何被投票的。
先感谢您。
作为流畅接口的消费者,我遇到的最大挑战是它们中的大多数并不是真正的流畅接口——相反,它们实际上是我倾向于称之为“易读接口”的实例。
流畅的界面意味着它的主要目标是使其易于说,而清晰的界面意味着其主要目标是易于阅读。大多数流畅的接口往往难以编写代码,但反过来又非常容易被其他人阅读。
Assert().That().This(actual).Is().Equal().To(expected).
Except().If(x => x.GreaterThan(10));
...比实际编写代码更容易阅读!
在你的第四点;
是的,我认为复杂的流畅界面仍然可以流畅。
我认为流畅的界面有点妥协。(虽然很好!)已经有很多关于使用自然语言进行编程的研究,并且通常自然语言不足以表达程序。
Fluent 接口的构造使得它们像编程语言一样编写,只允许您可以用自然语言表达的一小部分内容,但它们读起来像自然语言。
例如,如果您查看 rhino mocks,则与普通库相比,写作部分要复杂得多。由于流畅的界面,我花了更长的时间来学习,但它使代码更容易阅读。因为程序通常只编写一次,并且多次读取,这是一个很好的折衷方案。
所以要稍微说明一下我的观点。一个写起来复杂但易于阅读的流畅界面仍然可以流畅。
将继承与流式接口一起使用时,您会遇到困难,因为使用多态方法会破坏您的调用链,并且您绝对不想通过在不需要它们的地方使用丑陋的强制转换和括号来使您的接口不流利。我写了一篇关于一种模式的文章,它为您提供了一种使用通用构建器和通用扩展方法以及通用约束的解决方法:http: //liviutrifoi.wordpress.com/2009/02/16/fluent-interfaces-constraints-at-编译时/
Moq 隐藏了不相关的方法,例如 equals 等,ToString
以使其流畅的界面更易于使用。
隐藏系统对象是一篇解释这样做的好处的文章。
关于你的第二个和第三个问题;
我注意到的三种流畅模式
第一个使用 using 语句 (C# 2.0) 在特定上下文中运行代码,例如:
using(var transaction = new Transaction())
{
// ..
// ..
}
这使用 Transaction 的构造函数和处理器来设置事务,然后在此上下文中运行代码。
第二个几乎相同,但使用 lambda,这在 Rhino Mocks 中被大量使用。
(new Transaction()).Run( () => mycode(); );
最著名的 fluent 接口是使用返回类型来链接方法调用。大多数方法都会返回 this,因此您可以链接对同一对象的调用。但是您也可以根据调用的方法返回不同的对象来更改上下文。如果你有一个只能在事务中运行的对象(抱歉想不出一个不同的例子),你可以给它一个 StartTransaction 方法,它返回一个初始化的事务,你可以在伪代码中运行 call run 和 stoptransaction:
class Runner
{
Transaction StartTransaction()
{
return new Transaction(this);
}
}
class Transaction
{
Transaction Run()
Transaction StopTransaction()
}
电话的样子
var runner = new Runner();
runner
.StartTransaction()
.Run()
.StopTransaction();
当然,您需要添加各种错误处理等。
我也刚刚开始学习如何为工作中的小型应用程序编写流畅的界面。我四处询问并进行了一些研究,发现编写流畅界面的一种好方法是使用“构建器模式”,请在此处阅读更多信息。
本质上,这就是我开始我的方式:
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;
}
}
这是我在流畅界面中实现闭包的类似问题的交叉帖子。
一件事是您必须考虑英语语法的形态,并确保您没有在下面引入未记录的顺序耦合。
// Snarky employees get a raise.
employees.WhereSnarky().GiveRaise();
对比
// Depending on implementation, everyone may get a raise.
employees.GiveRaise().WhereSnarky();
前段时间我有你现在有同样的疑问。我已经做了一些研究,现在我正在写一些帖子来帮助这些主题。
在我的博客上查看:
在接下来的帖子中,我将涵盖您提到的每一点。
最好的问候安德烈·维安娜