Fluent API с ветвлениями
Хочется сделать для одной задачи, что-то такое, как сделано в Entity Framework, когда пишешь Include, а после него ThenInclude и можешь работать с объектом, который выбрал на прошлом шаге, а затем если написать Include, то снова возвращаешься к исходному объекту.
Хочу по итогу получить набор целых цепочек к свойствам от первого свойства и до последнего, который указал пользователь в цепочке.
Однако, не понимаю, как это все реализовывается. Скажем, как будет выглядеть иерархия и кто должен отвечать за агрегацию цепочек или нужно вообще организовывать двусвязных список...?
Надеюсь, я правильно объяснил.
Ответы (1 шт):
Сделать простенький FluentBuilder - дело нехитрое. Можно использовать интерфейсы, чтобы ограничивать отдельные операции. Вот пример
public class FluentBuilder :
FluentBuilder.IStageOne, FluentBuilder.IStageTwo, FluentBuilder.IStageFinal
{
Приватный конструктор, чтобы не было возможности создать экземпляр строителя ане класса. Элемент не обязательный, но часто встречается.
private FluentBuilder() {
_internalState = new StringBuilder();
_internalState.AppendLine("Start");
}
Внутреннее состояние класса
private StringBuilder _internalState = new StringBuilder();
Создание первого шага
public static IStageOne Create(){
return new FluentBuilder();
}
Операция вернет второй шаг
public IStageTwo OperationOne(string arg)
{
_internalState.AppendLine($"OperationOne with {arg}");
return this;
}
Возврат финального шага
public IStageFinal OperationTwo(string arg)
{
_internalState.AppendLine($"OperationTwo with {arg}");
return this;
}
Создание объекта из внутреннего состояния
public string Build()
{
_internalState.AppendLine("End");
return _internalState.ToString();
}
Мы не планируем иметь реализацию интерфейсов за пределами класса, потому держим их внутри класса.
public interface IStageOne
{
IStageTwo OperationOne(string arg);
}
public interface IStageTwo
{
IStageFinal OperationTwo(string arg);
}
public interface IStageFinal
{
String Build();
}
}
Пример использования
var result = FluentBuilder.Create()
.OperationOne("one")
.OperationTwo("two")
.Build();
Console.WriteLine(result);
Вывод
Start
OperationOne with one
OperationTwo with two
End