Рендеринг 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, который возвращает экземпляр, который он принимает, чтобы вызовы могли быть скованы. Аргумент, переданный лямбде, используемой в перегрузке, используемой при первом вызове "Тег", представляет собой "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, по крайней мере, эту идею.
Пожалуйста, дайте мне какие-нибудь соображения о том, как синтаксис можно улучшить, возможно, лучшие имена методов, возможно, какой-то другой подход все вместе.
Изменить: Я подумал, что было бы интересно посмотреть, как будет выглядеть тот же фрагмент без использования свободного интерфейса, для сравнения:
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, я думал об использовании методов расширения для добавления атрибутов, но я не могу использовать синтаксис индексатора, также он раздувает интерфейс HtmlTextWriter даже больше.