5

我正在编写RenderContents()我的 ASP.NET 服务器控件的方法。该方法使用HtmlTextWriter对象来呈现输出内容。对于我正在编写的控件,使用HtmlTextWriter's 方法似乎需要很多代码行来打开和关闭每个标签并将每个属性添加到流中。最后,我觉得我最终会得到比它需要的更长的代码。

我在想,如果我使用一个可链接的类,例如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;
    }
}
4

3 回答 3

10

我在开发一个应用程序,开发人员遵循您正在探索的可怕路径。这让人回想起您必须编写自己的 ISAPI dll 来输出 html 代码的日子。工作总是让人头疼。如果您的代码主要是字符串,那么就有问题了。

我更改的大多数这种类型的代码都会实例化服务器对象,根据需要配置它们的属性,然后将它们告诉 .RenderControl(writer)。这使代码更易于阅读和使用。如果这带来的开销对性能造成影响,我愿意接受(事实上,在我进行更改后,应用程序通常运行得更快,所以有趣的是,情况并非如此,但我没有分析我的代码)。

在字符串中硬编码您的内容的一个简单缺点是 HTML 标准发生变化时。我工作的代码是在 04/05 编写的,从那时起 <BR> 变成了 <br /> 并且大写的 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,因为我没有任何硬编码的字符串。

于 2009-01-28T22:44:07.230 回答
4

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

于 2009-01-28T22:32:21.730 回答
1

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

我看不出使用字符串生成器如何节省使用 HtmlTextWriters 自己的方法的任何工作。

于 2009-01-28T22:36:29.540 回答