Свободный интерфейс для рендеринга HTML

По моему мнению, рендеринг HTML с помощью HtmlTextWriter не очень интуитивно понятен, но если вы реализуете веб-элементы управления в веб-формах, это то, с чем вам придется работать. Я подумал, что можно было бы создать свободный интерфейс для этого, который читается немного больше, чем HTML, который он выводит. Я хотел бы знать, что люди думают о синтаксисе, который я придумал до сих пор.

    public void Render(HtmlTextWriter writer)
    {
        writer
            .Tag(HtmlTextWriterTag.Div, e => e[HtmlTextWriterAttribute.Id, "id"][HtmlTextWriterAttribute.Name,"name"][HtmlTextWriterAttribute.Class,"class"])
                .Tag(HtmlTextWriterTag.Span)
                    .Text("Lorem")
                .EndTag()
                .Tag(HtmlTextWriterTag.Span)
                    .Text("ipsum")
                .EndTag()
            .EndTag();        
    }

«Tag», «Text» и «EndTag» являются методами расширения для класса HtmlTextWriter, который возвращает экземпляр, который он принимает, чтобы вызовы могли быть связаны. Аргумент, передаваемый лямбда-выражению, используемому в перегрузке, используемой при первом вызове «Tag», является «HtmlAttributeManager», который представляет собой простой класс, который оборачивает HtmlTextWriter для предоставления индексатора, который принимает HtmlTextWriterAttribute и строковое значение и возвращает экземпляр так, эти звонки могут быть прикованы цепью. У меня также есть методы для этого класса для наиболее распространенных атрибутов, таких как «Имя», «Класс» и «Идентификатор», чтобы вы могли написать первый вызов выше следующим образом:

.Tag(HtmlTextWriterTag.Div, e => e.Id("id").Name("name").Class("class"))

Немного более длинный пример:

public void Render(HtmlTextWriter writer)
{
    writer
        .Tag(HtmlTextWriterTag.Div, a => a.Class("someClass", "someOtherClass"))
            .Tag(HtmlTextWriterTag.H1).Text("Lorem").EndTag()
            .Tag(HtmlTextWriterTag.Select, t => t.Id("fooSelect").Name("fooSelect").Class("selectClass"))
                .Tag(HtmlTextWriterTag.Option, t => t[HtmlTextWriterAttribute.Value, "1"][HtmlTextWriterAttribute.Title, "Selects the number 1."])
                    .Text("1")
                .EndTag(HtmlTextWriterTag.Option)
                .Tag(HtmlTextWriterTag.Option, t => t[HtmlTextWriterAttribute.Value, "2"][HtmlTextWriterAttribute.Title, "Selects the number 2."])
                    .Text("2")
                .EndTag(HtmlTextWriterTag.Option)
                .Tag(HtmlTextWriterTag.Option, t => t[HtmlTextWriterAttribute.Value, "3"][HtmlTextWriterAttribute.Title, "Selects the number 3."])
                    .Text("3")
                .EndTag(HtmlTextWriterTag.Option)
            .EndTag(HtmlTextWriterTag.Select)
        .EndTag(HtmlTextWriterTag.Div);
}

Надеюсь, вы сможете «расшифровать», какой HTML выводит этот фрагмент, по крайней мере, в этом идея.

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

Edit: я подумал, что было бы интересно посмотреть, как будет выглядеть тот же фрагмент без использования плавного интерфейса, для сравнения:

public void RenderUsingHtmlTextWriterStandardMethods(HtmlTextWriter writer)
{
    writer.AddAttribute(HtmlTextWriterAttribute.Class, "someClass someOtherClass");
    writer.RenderBeginTag(HtmlTextWriterTag.Div);

    writer.RenderBeginTag(HtmlTextWriterTag.H1);
    writer.Write("Lorem");
    writer.RenderEndTag();

    writer.AddAttribute(HtmlTextWriterAttribute.Id, "fooSelect");
    writer.AddAttribute(HtmlTextWriterAttribute.Name, "fooSelect");
    writer.AddAttribute(HtmlTextWriterAttribute.Class, "selectClass");
    writer.RenderBeginTag(HtmlTextWriterTag.Select);

    writer.AddAttribute(HtmlTextWriterAttribute.Value, "1");
    writer.AddAttribute(HtmlTextWriterAttribute.Title, "Selects the number 1.");
    writer.RenderBeginTag(HtmlTextWriterTag.Option);
    writer.Write("1");
    writer.RenderEndTag();

    writer.AddAttribute(HtmlTextWriterAttribute.Value, "2");
    writer.AddAttribute(HtmlTextWriterAttribute.Title, "Selects the number 2.");
    writer.RenderBeginTag(HtmlTextWriterTag.Option);
    writer.Write("2");
    writer.RenderEndTag();

    writer.AddAttribute(HtmlTextWriterAttribute.Value, "3");
    writer.AddAttribute(HtmlTextWriterAttribute.Title, "Selects the number 3.");
    writer.RenderBeginTag(HtmlTextWriterTag.Option);
    writer.Write("3");
    writer.RenderEndTag();

    writer.RenderEndTag();

    writer.RenderEndTag();
}

РЕДАКТИРОВАТЬ: Я, вероятно, должен быть немного более четким в том, что одна из целей этого заключается в том, что это должно повлечь за собой как можно меньше накладных расходов, поэтому я ограничил использование лямбд. Также сначала я использовал класс, представляющий тег, чтобы синтаксис перед рендерингом создавал нечто похожее на DOM-дерево, хотя синтаксис был очень похожим. Я отказался от этого решения из-за небольших накладных расходов памяти, которые оно несет. Некоторые из них присутствуют при использовании класса HtmlAttributeManager. Я думал о том, чтобы использовать методы расширения и для добавления атрибутов, но я не могу использовать синтаксис indexer, также он раздувает интерфейс HtmlTextWriter. даже больше.

Ответы на вопрос(4)

Ваш ответ на вопрос