有条件的构建方法链接流畅的界面 [英] Conditional Builder Method Chaining Fluent Interface
问题描述
我想知道什么是执行在流畅接口的。当
情况的最好办法是方式链接在生成器
对象?
I was wondering what would be the best way to implement a .When
condition in a fluent interface using method chaining in a Builder
object?
比如我将如何贯彻落实 .WithSkill ()
和。当()
在下面的示例中的方法:
For instance how would I implement the .WithSkill()
and .When()
methods in the following example:
var level = 5;
var ninja = NinjaBuilder
.CreateNinja()
.Named("Ninja Boy")
.AtLevel(level)
.WithShurikens(10)
.WithSkill(Skill.HideInShadows)
.When(level > 3)
.Build()
更新 - 样品溶液可以发现的这里。
Update - A sample solution can be found here.
推荐答案
我会做的是有 NinjaBuilder
保持业务为代表的列表,而不是将它们,只适用于他们时,被称为 .Build
。这将允许您以使其有条件的:
What I'd do is have NinjaBuilder
keep the operations as a list of delegates, rather than applying them, and only apply them when .Build
is called. This would allow you to make them conditional:
public class NinjaBuilder {
List<Action<Ninja>> builderActions = new List<Action<Ninja>>();
public Ninja Build() {
var ninja = new Ninja();
builderActions.ForEach(ba => ba(ninja));
return ninja;
}
public NinjaBuilder WithShurikens(int numShirukens) {
builderActions.Add(n=>n.Shirukens = numShirukens);
return this;
}
public NinjaBuilder When(Boolean condition) {
if (!condition) // If the condition is not met, remove the last action
builderActions.Remove(builderActions.Length - 1);
return this;
}
}
当然,这个假设条件是恒定在建设者创造的时候。如果你想让它不恒定,你可以做这样的事情,而不是:
Of course, this assumes that the condition is constant at the time of builder creation. If you want to make it non-constant, you could do something like this instead:
public NinjaBuilder When(Func<Boolean> condition) {
var oldAction = builderActions[builderActions.Length - 1];
builderActions[builderActions.Length - 1] = n => condition() ? oldAction(n) : n;
return this;
}
如果你想在
将较为编译器检查,可以使受保护的builderActions,做这样的事情:
If you want When
be somewhat more compiler checked, you can make builderActions protected and do something like this:
public class ConditionalNinjaBuilder : NinjaBuilder {
public ConditionalNinjaBuilder(NinjaBuilder wrappedBuilder) {
// Since someone might call .WithShirukens on the wrapping
// builder directly, we should make sure that our actions
// list is the same instance as the one in our wrapped builder
builderActions = wrappedBuilder.builderActions;
}
public ConditionalNinjaBuilder When(Func<Boolean> condition) {
var oldAction = builderActions[builderActions.Length - 1];
builderActions[builderActions.Length - 1] = n => condition() ? oldAction(n) : n;
return this;
}
}
和具有原始操作返回一个ConditionalNinjaBuilder:
and have the original operations return a ConditionalNinjaBuilder:
public ConditionalNinjaBuilder WithShurikens(int numShirukens) {
builderActions.Add(n=>n.Shirukens = numShirukens);
return new ConditionalNinjaBuilder(this);
}
这样,你只能叫。当后首次调用另一个方法code>。这有可能允许嵌套/复合条件语句额外的优势/并发症,太。让人惊讶。
That way you can only call .When
after first calling another method. This has the additional advantage/complication of potentially allowing for nested/compounded conditionals, too. Yikes.
这篇关于有条件的构建方法链接流畅的界面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!