Использование HtmlTextWriter для рендеринга серверных элементов управления?
-
20-08-2019 - |
Вопрос
Я пишу RenderContents()
метод моего ASP.NET управления сервером.Метод использует HtmlTextWriter
объект для отображения выходного содержимого.Для элемента управления, который я пишу, используя HtmlTextWriter
похоже, что для использования методов потребуется много строк кода, чтобы открывать и закрывать каждый тег и добавлять каждый атрибут в поток.В конце концов, я чувствую, что в итоге у меня получится код, который намного длиннее, чем должен быть.
Я подумал, что если бы я использовал цепочечный класс, такой как StringBuilder
, мой код был бы намного чище для чтения и проще в написании.
Что мне было интересно, так это то, есть ли какая-либо причина использовать HtmlTextWriter
возражаете против отображения всего содержимого моего элемента управления?Помимо проверок безопасности (я предполагаю), которые он включает, чтобы убедиться, что вы не пишете теги в неправильном порядке или не создаете недопустимую разметку, я не вижу причин.
Кажется, было бы проще просто сделать что-то подобное:
protected override void RenderContents(HtmlTextWriter output)
{
StringBuilder s = new StringBuilder();
s.Append("lots")
.Append("of")
.Append("strings");
output.BeginRender();
output.Write(s.ToString());
output.EndRender();
}
Есть ли какая-то причина, по которой это было бы плохой идеей?
Обновить
В ответ на Мехрдад Афшариответ 's:
Я не особо задумывался о требованиях к памяти, связанных с наличием отдельного StringBuilder
создан экземпляр объекта.Как насчет создания оболочки для HtmlTextWriter, чтобы ее можно было связать цепочкой, чтобы не создавалась дополнительная строка?
public class ChainedHtmlTextWriter
{
private HtmlTextWriter _W;
public ChainedHtmlTextWriter(HtmlTextWriter writer)
{
_W = writer;
}
public ChainedHtmlTextWriter Write<T>(T value)
{
_W.Write(value);
return this;
}
public ChainedHtmlTextWriter WriteLine<T>(T value)
{
_W.WriteLine(value);
return this;
}
}
Решение
Я работаю над приложением, разработчики которого пошли по тому ужасному пути, который вы исследуете.Это возвращает к тем дням, когда вам приходилось писать свои собственные библиотеки DLL ISAPI, которые выдавали html-код.Работать с этим - постоянная головная боль.Если ваш код в основном состоит из строк, значит, что-то не так.
Большую часть кода этого типа, который я изменяю, я создаю экземпляры серверных объектов, настраиваю их свойства по желанию, а затем передаю их в .RenderControl(writer).Это значительно облегчает чтение кода и работу с ним.Если это приводит к снижению производительности из-за накладных расходов, я готов принять это (на самом деле, приложение обычно работает быстрее после того, как я внес свои изменения, так что, как ни странно, это не так, но я не профилировал свой код).
Один простой недостаток жесткого кодирования ваших материалов в строках заключается в изменении стандартов HTML.Код, над которым я работаю, был написан 04/05, и с тех пор <BR> стал <br /> и заглавные html-теги больше не являются кошерными и т.д.Если бы они использовали серверные элементы управления, эти серверные элементы управления изменили бы свой выводимый HTML-код без необходимости нам что-либо делать.Это всего лишь один простой пример.
Редактировать:Да, и кстати, BeginRender и EndRender не имеют никакой реализации.Они являются заполнителями, которые вы можете переопределить и предоставить пользовательскую функциональность в классе, производном от HtmlTextWriter.
РЕДАКТИРОВАТЬ 2:Иногда это немного обременительно для всегда используйте серверные элементы управления, например, для контейнеров и прочего.Я бы сделал много .Controls.Add(), а затем отрисовал контейнер позже.Поэтому иногда я делаю это:
writer.AddAttribute(HtmlTextWriterAttribute.Class, "myContainerClass");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
// do some stuff, .RenderControl on some other controls, etc.
writer.RenderEndTag();
Как уже упоминалось, это приведет к отображению правильного html, даже если html div изменится в будущем, потому что у меня нет никаких жестко закодированных строк.
Другие советы
С точки зрения производительности для этого потребуется выполнить больше копий строк. HtmlTextWriter
записывает непосредственно в выходной буфер. StringBuilder
с другой стороны, имеет свой собственный буфер.Когда ты позвонишь ToString
на StringBuilder
, необходимо создать новую строку , а затем она будет записана в выходной буфер с помощью output.Write
.Для этого требуется проделать гораздо больше работы.
Я не думаю, что вам следует вызывать BeginRender / EndRender, это делается страницей.
Я не вижу, как использование string builder сэкономило бы какую-либо работу по сравнению с использованием собственных методов HtmlTextWriters.