Fluent API с ветвлениями

Хочется сделать для одной задачи, что-то такое, как сделано в Entity Framework, когда пишешь Include, а после него ThenInclude и можешь работать с объектом, который выбрал на прошлом шаге, а затем если написать Include, то снова возвращаешься к исходному объекту.

Хочу по итогу получить набор целых цепочек к свойствам от первого свойства и до последнего, который указал пользователь в цепочке.

Однако, не понимаю, как это все реализовывается. Скажем, как будет выглядеть иерархия и кто должен отвечать за агрегацию цепочек или нужно вообще организовывать двусвязных список...?

Надеюсь, я правильно объяснил.


Ответы (1 шт):

Автор решения: tym32167

Сделать простенький 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
→ Ссылка