Рендеринг 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();
}
EDIT:
Я, вероятно, должен быть немного более ясным в том, что одной из целей этого является то, что это должно повлечь за собой как можно меньше накладных расходов, поэтому я ограничил использование лямбд. Также сначала я использовал класс, представляющий тег, чтобы синтаксис перед рендерингом создавал нечто похожее на DOM-дерево, хотя синтаксис был очень похожим. Я отказался от этого решения из-за небольших накладных расходов памяти, которые оно несет. Некоторые из них присутствуют при использовании класса HtmlAttributeManager. Я думал о том, чтобы использовать методы расширения и для добавления атрибутов, но я не могу использовать синтаксис indexer, также он раздувает интерфейс HtmlTextWriter. еще больше.