让我的 class 'fluent'
Making my class 'fluent'
我昨天发现,如果我 return 来自每个方法的 class 实例,我可以 模拟 一个流畅的界面...
public class IsThisFluent
{
public IsThisFluent Stuff()
{
//...
return this;
}
public IsThisFluent OtherStuff()
{
// ...
return this;
}
}
仅此而已吗?
我承认,我是一只脑袋很小的熊,我想继续这个,但我认为最好还是和大人核实一下。
我是不是漏掉了什么?
有没有 'gotcha' 我没有发现这种模式?
不,差不多就是这样。
其背后的想法是,您可以将方法调用链接在一起,以随时操纵内部状态。 Fluent interface 的最终主要目标是可读性,LINQ 就是一个很好的例子。
差不多就这些了。
这是一篇关于它的非常好的文章:
http://rrpblog.azurewebsites.net/?p=33
编辑
原来的网站似乎已经死了,所以这里是WayBackMachine to the rescue
我也非常喜欢这个答案中的这个例子:
public class Coffee
{
private bool _cream;
public Coffee Make { get new Coffee(); }
public Coffee WithCream()
{
_cream = true;
return this;
}
public Coffee WithOuncesToServe(int ounces)
{
_ounces = ounces;
return this;
}
}
var myMorningCoffee = Coffee.Make.WithCream().WithOuncesToServe(16);
这提醒了我,我现在需要一杯咖啡。
return this
不是 all 有流畅的界面。
链接方法是构建流式 API 的一种简单形式,但流式 API 通常看起来像 DSL(领域特定语言),并且 很多 更难实现设计。
以最小起订量为例:
new Mock<IInterface>()
.Setup(x => x.Method())
.CallBack<IInterface>(Console.WriteLine)
.Returns(someValue);
Setup
方法,定义在Mock<T>
类型上,returns是ISetup<T, TResult>
的一个实例。
Callback
方法,为 ICallback<TMock, TResult>
returns IReturnsThrows<TMock,TResult>
的实例定义。请注意 ISetup<T, TResult>
扩展了 IReturnsThrows<TMock,TResult>
.
最后,Returns
定义在IReturns<TMock,TResult>
和returnsIReturnsResult<TMock>
上。另请注意 IReturnsThrows<TMock,TResult>
扩展了 IReturnsResult<TMock>
.
所有这些细微差别都是为了强制您以特定顺序调用这些方法,并禁止您连续调用 Setup
两次,例如。或者在调用 Setup
.
之前调用 Returns
这些细节对于确保良好的用户体验非常重要。
要阅读有关设计流畅界面的更多信息,请查看 Martin Fowler 关于 FluentInterface. FluentAssertions 的文章,这是设计可能变得多么复杂的另一个主要示例 - 但结果的可读性也更高。
我昨天发现,如果我 return 来自每个方法的 class 实例,我可以 模拟 一个流畅的界面...
public class IsThisFluent
{
public IsThisFluent Stuff()
{
//...
return this;
}
public IsThisFluent OtherStuff()
{
// ...
return this;
}
}
仅此而已吗?
我承认,我是一只脑袋很小的熊,我想继续这个,但我认为最好还是和大人核实一下。
我是不是漏掉了什么?
有没有 'gotcha' 我没有发现这种模式?
不,差不多就是这样。
其背后的想法是,您可以将方法调用链接在一起,以随时操纵内部状态。 Fluent interface 的最终主要目标是可读性,LINQ 就是一个很好的例子。
差不多就这些了。
这是一篇关于它的非常好的文章:
http://rrpblog.azurewebsites.net/?p=33
编辑
原来的网站似乎已经死了,所以这里是WayBackMachine to the rescue
我也非常喜欢这个答案中的这个例子:
public class Coffee
{
private bool _cream;
public Coffee Make { get new Coffee(); }
public Coffee WithCream()
{
_cream = true;
return this;
}
public Coffee WithOuncesToServe(int ounces)
{
_ounces = ounces;
return this;
}
}
var myMorningCoffee = Coffee.Make.WithCream().WithOuncesToServe(16);
这提醒了我,我现在需要一杯咖啡。
return this
不是 all 有流畅的界面。
链接方法是构建流式 API 的一种简单形式,但流式 API 通常看起来像 DSL(领域特定语言),并且 很多 更难实现设计。
以最小起订量为例:
new Mock<IInterface>()
.Setup(x => x.Method())
.CallBack<IInterface>(Console.WriteLine)
.Returns(someValue);
Setup
方法,定义在Mock<T>
类型上,returns是ISetup<T, TResult>
的一个实例。Callback
方法,为ICallback<TMock, TResult>
returnsIReturnsThrows<TMock,TResult>
的实例定义。请注意ISetup<T, TResult>
扩展了IReturnsThrows<TMock,TResult>
.最后,
Returns
定义在IReturns<TMock,TResult>
和returnsIReturnsResult<TMock>
上。另请注意IReturnsThrows<TMock,TResult>
扩展了IReturnsResult<TMock>
.
所有这些细微差别都是为了强制您以特定顺序调用这些方法,并禁止您连续调用 Setup
两次,例如。或者在调用 Setup
.
Returns
这些细节对于确保良好的用户体验非常重要。
要阅读有关设计流畅界面的更多信息,请查看 Martin Fowler 关于 FluentInterface. FluentAssertions 的文章,这是设计可能变得多么复杂的另一个主要示例 - 但结果的可读性也更高。