茂爷的博客
:: 向左走向右走::

在相遇的城市迷失之前
寻找一张似曾相识的脸
握在手中的风筝
断了线
是因为我寂寞
你才出现
还是你的存在让我自怜
缘分走过我身边
变成答录机遥远的留言
甜蜜在梦幻的一瞬间
留下了真实的思念
一段情就能连接两个人的天
一条路就能让两个人霎那之间
命运都改变
只要愿意相信就能相见
一滴泪就能挡住两个人的天
模糊我的视线
呼唤着你名字
从起点回到原点
两条平行线总有交汇的一天
是命运在转变
你才出现
还是你的出现让我改变
一个巧合的意外
变成一场最执着的迷恋
甜蜜在梦幻的一瞬间
留下了真实的思念

One of the things that was introduced in .NET 2.0 was a new mechanism for managing registration of client script into the page, via the new ClientScriptManager class, instead of the page's dedicated RegisterClientScriptBlock method. In the process of moving the API, MS also saw fit to add a new Type parameter to the method.

This reflects the fact that the best practice when calling Page.RegisterClientScriptBlock was to formulate a unique key for your script that incorporated the fully qualified name of the class doing the registration of the script, as a way to avoid unseemly *****es between script registrations. That way, only one copy of the script for a particular control gets registered per page, no matter how many such controls appear on the page - and at the same time, the script shouldn't trample on the scripts needed by other controls.

With ClientScriptManager, you're spared the need to formulate the name for your script to incorporate said fully qualified typename by the API, which asks you to pass a type object in, which it will use to uniquely key all the scripts registered.

So far so good. The one fly in the ointment for anyone calling the new API is figuring out how to actually obtain an appropriate type object to pass in.

The MSDN example code, and all the other examples I can find, the idiom adopted seems to be:

Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "Script", scriptText);

 

This is not good. Why not? Well, this.GetType() is a way of getting the runtime type of an object. That's not necessarily the same type as the one in which this bit of code is being declared.

So what? Does that actually make any difference? Well, yes, if anyone ever writes a control that inherits from your control.

If I create a control called Widget that calls RegisterClientScriptBlock() passing this.GetType(), then whenever I put a few Widget controls on the page, the script block will be registered once, and only once. That's great.

Then later on, I develop a SpecialisedWidget control that inherits from Widget. I drop it onto the page, and suddenly, RegisterClientScriptBlock is getting called with the same script, but two different types - Widget, and SpecialisedWidget. The script block ends up appearing on the page twice. Cue tricky hard to track JavaScript bugs that take ages to find...

Now, if Widget had originally registered that script block passing typeof (Widget) as the type argument instead of this.GetType(), the whole problem wouldn't arise, because even when the SpecialisedWidgets are registering script on the page, the script is registered with the type qualifier of Widget. And as a side bonus, the IL will be more efficient, because typeof (Widget) is a kind of type literal, which the compiler can embed right into the code, rather than a runtime dispatched method call to a reflection API.

So the lesson of the day is, use typeof to get a static compile-time type reference when calling the ASP.NET 2.0 RegisterClientScriptBlock method, not GetType() to get a dynamic runtime type.

posted on 2010-05-25 11:32  茂爷的blog  阅读(87)  评论(0)    收藏  举报