使用HtmlTextWriter渲染服务器控件?

时间:2009-01-28 22:26:27

标签: asp.net stringbuilder servercontrols htmltextwriter method-chaining

我正在编写ASP.NET服务器控件的RenderContents()方法。该方法使用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();
}

有什么理由说这是一个坏主意吗?

更新
回答Mehrdad Afshari的回答:
 我没有考虑实例化单独的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;
    }
}

3 个答案:

答案 0 :(得分:10)

我致力于开发人员遵循您正在探索的可怕路径的应用程序。这让我们回想起你必须编写自己的ISAPI dll的日子,这些dll吐出了html代码。工作中一直是一个令人头痛的问题。如果你的代码主要是字符串,那么就会出现问题。

我改变的这种类型的大多数代码我实例化服务器对象,根据需要配置它们的属性,然后告诉它们.RenderControl(writer)。这使代码更易于阅读和使用。如果这带来了性能损失,我愿意接受它(实际上,应用程序通常在我做出更改后运行得更快,所以传闻情况并非如此,但我还没有描述过我的代码)。

在字符串中对内容进行硬编码的一个简单缺点是HTML标准发生变化。我工作的代码是在04/05写的,从那以后&lt; BR&gt;已成为&lt; br /&gt;和大写的html标签不再是Kosher等等。如果他们一直在使用服务器控件,那些服务器控件已经更改了他们输出的html而我们不需要做任何事情。这只是一个简单的例子。

编辑:哦,顺便说一句,BeginRender和EndRender没有任何实现。它们是占位符,您可以在HtmlTextWriter派生类中覆盖和提供自定义功能。

EDIT2:有时候总是使用服务器控件,比如容器和东西,这有点麻烦。我会做很多.Controls.Add()然后再渲染容器。所以有时我会这样做:

writer.AddAttribute(HtmlTextWriterAttribute.Class, "myContainerClass");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
// do some stuff, .RenderControl on some other controls, etc.
writer.RenderEndTag();

如上所述,即使div的html在将来发生变化,这也会呈现正确的html,因为我没有任何硬编码的字符串。

答案 1 :(得分:4)

在性能方面,这将需要更多的字符串副本。 HtmlTextWriter直接写入输出缓冲区。另一方面,StringBuilder有自己的缓冲区。当您在ToString上调用StringBuilder时,必须构建一个新字符串,然后由output.Write将其写入输出缓冲区。这需要做更多的工作。

答案 2 :(得分:1)

我不认为你应该调用BeginRender / EndRender,这是由页面完成的。

我无法看到使用字符串生成器如何使用HtmlTextWriters自己的方法保存任何工作。