Fluent Builder 模式

前言

以前最讨厌设计复杂方法调用, 就是那种需要一堆有逻辑规则的 config 作为参数的方法. 

这种 config 通常是一个大对象, 有许多 property, property 之间有存在一些逻辑, 比如当 property A 是什么的时候 B 必须也是什么.

如果不管它, 那么调用方法的人就会很幸苦, 一直到 runtime 才会报错.

 

Fluent Builder 模式

Fluent Builder 模式就是用来有条有理的创建复杂对象的. 比如上面说到的 config.

很多地方都可以看到它的影子.

EF Core 和 OData 都用了这个方式来创建 model.

FluentValidation 也是用了这个方式来创建 validation rules

 

如何实现

参考: Fluent Builder模式简介

其内部原理就是通过几个小的 builder, 每一个 builder 负责一部分创建. 然后串起来.

每一个小 builder 就可以通过方法, 去声明类型, 和限制调用顺序等.

虽然它不能 100% 解决使用者调用错误的问题, 但是已经非常多了. 

在设计方法调用的时候, 我们不可以认为使用者是开发人员就顺便的做, 应该要尽可能让调用简单, 智能, 有类型推倒.

before 

builder.HasPrincipalProperty(e => e.ProductName, e => e.Color.Product.Name, conditionalInfo: new RedundancyExpressionVersionConditionalInfo<Size>
{
    WhereExpression = e => e.Type == SizeType.TypeA,
    WhenNoInCondition = WhenNoInCondition.AutomaticallySetToNull
});
builder.HasPrincipalProperty(e => e.ProductId, e => e.Color.Product.Id, conditionalInfo: new RedundancyExpressionVersionConditionalInfo<Size>
{
    WhereExpression = e => e.Type == SizeType.TypeA,
    WhenNoInCondition = WhenNoInCondition.AutomaticallySetToNull
});
builder.HasPrincipalProperty(e => e.Age, e => e.Color.Product.Age, conditionalInfo: new RedundancyExpressionVersionConditionalInfo<Size>
{
    WhereExpression = e => e.Type == SizeType.TypeA,
    WhenNoInCondition = WhenNoInCondition.AutomaticallySetToNull
});

after

builder.HasPrincipalProperty()
    .Relation(e => e.Color.Product)
    .PropertyMap(e => e.ProductName, e => e.Name)
    .PropertyMap(e => e.ProductAge, e => e.Age)
    .PropertyMap(e => e.ProductId, e => e.Id)
    .Conditional(condition =>
    {
        condition.WhereExpression = e => e.Type == SizeType.TypeA;
        condition.WhenNoInCondition = WhenNoInCondition.SetValueManually;
    });

这个例子里面有点复杂, 不适合用作教学, 看看调用自己揣摩一下就好.

 

posted @ 2022-01-05 17:30  兴杰  阅读(276)  评论(0编辑  收藏  举报