Teenits 2008-5-24 16:57
ASP.NET效率陷阱之——Attributes
作者: 出处: cnblogs
[font=Tahoma] 众所周知,在编写WebCustomControl时,继承于WebControl基类的Attributes以及其Attributes.CssStyle属性是十分常用和重要的。但就是这两个重要的属性,如果开发中使用不当却会带来莫名其妙的效率问题。
由于html的灵活性和不完备性,导致了WebControl基类没有完整的表现html元素所提供和支持的所有标签属性和CSS属性(当然由于不同browser的兼容问题,要提供完备的属性是不可能的)。又由于很多html标签属性和CSS属性都是很生僻的,很少或极少被使用,如果要完备的支持,反而会成为WebControl的负担。所以Attributes和Attributes.CssStyle这两个属性很好的解决了这个问题,当然这两个属性除了支持应有的html标签属性和CSS属性外,还支持任何合法的自定义key/value对。这里要讨论的问题就来之这个对自定义key/value对的支持上。
Attributes属性的类型是一个AttributeCollection,本来很自然的一个东西,可是不知道怎么搞得,AttributeCollection的构造函数却需要一个StateBag参数:[/font]
[size=13px][font=Tahoma][img]http://dev.yesky.com/imagelist/2007/078/qs6o13i497et.gif[/img][color=#00ff]public[/color][/font][font=Tahoma][color=#000] AttributeCollection(StateBag bag)
[img]http://dev.yesky.com/imagelist/2007/078/88j352030b51.gif[/img][img]http://dev.yesky.com/imagelist/2007/078/vi0f3qu00974.gif[/img][/color][img]http://dev.yesky.com/imagelist/2007/078/j87rrs6nptx4.gif[/img][/font][font=Tahoma][color=#000]{
[img]http://dev.yesky.com/imagelist/2007/078/4a209pfblm6t.gif[/img] [/color][color=#00ff]this[/color][color=#000]._bag [/color][color=#000]=[/color][/font][color=#000][font=Tahoma] bag;
[img]http://dev.yesky.com/imagelist/2007/078/73v965nc18dr.gif[/img]}[/font][/color][/size]
[font=Tahoma] 这样的结果就是,Attributes和Attributes.CssStyle可能会被保存在ViewState中,事实上ASP.NET默认确实会保存其中的内容到ViewState中。
这种[url=http://design.yesky.com/]设计[/url]真的是让人觉得莫名其妙,在大家对ViewState效率问题的讨论中,觉得ViewState确实是鸡肋,用来保持一些服务器状态和数据让大家觉得方便也就算了。可是居然把和UI相关的内容都一股脑存到ViewState里,真的是疯狂。
下面是使用Attributes定义了一些自定义内容后的ViewState的情形:
[url=http://dev.yesky.com/syscore/196/474696d_6.shtml][img]http://dev.yesky.com/imagelist/2007/078/0zj24yy9rx78s.png[/img][/url]
[i][color=#808080] // AnalysisReport自定义控件上定义了一些自定的内容
[/color][/i]
Attributes和Attributes.CssStyle被自动保存到ViewState中后,除了ViewState体积急增后,PostBack时Load ViewState的负担也同时增大了。上面这个事例中的页面PostBack的LoadState代价,如下图:
[url=http://dev.yesky.com/syscore/196/474696d_7.shtml][img]http://dev.yesky.com/imagelist/2007/078/ot96o8c2ukt6s.png[/img][/url]
实际上我在编写控件时,从来没有想过要保持Attributes和Attributes.CssStyle,也没有想过要再次使用其中的数据。而且这个默认保存到ViewState的行为居然不能定制(至少我还没有发现),后来想到在ASP.NET页面生存期中,SaveState结束在PreRender中,所以在Render事件中使用Attributes和Attributes.CssStyle的就不会保存到ViewState中去。
修改代码:
[size=13px][img]http://dev.yesky.com/imagelist/2007/078/4sg9oe982242.gif[/img][color=#00ff]protected[/color]
[color=#00ff]override[/color]
[color=#00ff]void[/color][color=#000] OnPreRender(EventArgs e)
[img]http://dev.yesky.com/imagelist/2007/078/f0e5p80puc19.gif[/img][img]http://dev.yesky.com/imagelist/2007/078/iry7f18939sg.gif[/img][/color][img]http://dev.yesky.com/imagelist/2007/078/6jd65ubw1b13.gif[/img][color=#000]{
[img]http://dev.yesky.com/imagelist/2007/078/25gzr399e72b.gif[/img] [/color][color=#00ff]this[/color][color=#000].Attributes[[/color][color=#000]"[/color][color=#000]abc[/color][color=#000]"[/color][color=#000]] [/color][color=#000]=[/color]
[color=#000]"[/color][color=#000]123[/color][color=#000]"[/color][color=#000];
[img]http://dev.yesky.com/imagelist/2007/078/c4t0n47782bq.gif[/img] [/color][color=#00ff]this[/color][color=#000].Attributes.CssStyle[[/color][color=#000]"[/color][color=#000]abc-style[/color][color=#000]"[/color][color=#000]] [/color][color=#000]=[/color]
[color=#000]"[/color][color=#000]123-style[/color][color=#000]"[/color][color=#000];
[img]http://dev.yesky.com/imagelist/2007/078/lmtnj0jk6c00.gif[/img] [/color][color=#00ff]base[/color][color=#000].OnPreRender(e);
[img]http://dev.yesky.com/imagelist/2007/078/9qpt7f6k7ehq.gif[/img]}[/color][/size]
[/font]
为如下形式:
[size=13px][img]http://dev.yesky.com/imagelist/2007/078/1w056j8ej350.gif[/img][color=#00ff]protected[/color]
[color=#00ff]override[/color]
[color=#00ff]void[/color][color=#000] Render(HtmlTextWriter output)
[img]http://dev.yesky.com/imagelist/2007/078/28ftzf5o7o2t.gif[/img][img]http://dev.yesky.com/imagelist/2007/078/t585i2761f2f.gif[/img][/color][img]http://dev.yesky.com/imagelist/2007/078/80s7sxh7w47h.gif[/img][color=#000]{
[img]http://dev.yesky.com/imagelist/2007/078/k8a660z63dch.gif[/img] [/color][color=#00ff]this[/color][color=#000].Attributes[[/color][color=#000]"[/color][color=#000]abc[/color][color=#000]"[/color][color=#000]] [/color][color=#000]=[/color]
[color=#000]"[/color][color=#000]123[/color][color=#000]"[/color][color=#000];
[img]http://dev.yesky.com/imagelist/2007/078/81e89g4pplkk.gif[/img] [/color][color=#00ff]this[/color][color=#000].Attributes.CssStyle[[/color][color=#000]"[/color][color=#000]abc-style[/color][color=#000]"[/color][color=#000]] [/color][color=#000]=[/color]
[color=#000]"[/color][color=#000]123-style[/color][color=#000]"[/color][color=#000];
[img]http://dev.yesky.com/imagelist/2007/078/58l2132v8f0u.gif[/img] output.Write(Text);
[img]http://dev.yesky.com/imagelist/2007/078/j66594tx02s0.gif[/img]}[/color][/size]
就不会再将Attributes和Attributes.CssStyle保存到ViewState中了,上面那个AnalysisReport按上面的示例修改后,绑定同样数据的运行效果为:
[url=http://dev.yesky.com/syscore/196/474696d_24.shtml][img]http://dev.yesky.com/imagelist/2007/078/6y816vq7yr07s.png[/img][/url]
LoadState的代价也大大降低,其开销为:
[url=http://dev.yesky.com/syscore/196/474696d_25.shtml][img]http://dev.yesky.com/imagelist/2007/078/56vb2097tga6s.png[/img][/url]