知识大全 细节决定成败 ASP.NET中的蝴蝶效应

Posted

篇首语:苦心人天不负,卧薪尝胆,三千越甲可吞吴。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 细节决定成败 ASP.NET中的蝴蝶效应相关的知识,希望对你有一定的参考价值。

细节决定成败 ASP.NET中的蝴蝶效应  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  前言

  ASP NET的优点我说过很多次了 也就是各个控件独立负责自己内部的逻辑 这是一个好事情 因为它解决了原本ASP处理逻辑耦合度高的问题 然而这是需要代价的 那就是引入ASP NET页面生命周期 随着控件的多层嵌套 应用的复杂度增加 我们再次陷入泥潭!

  问题

  其实这个文章题目我两个月前就写下了 可是一直没想写完它 直到今天我在这个泥潭中泡了几个小时 于是决定先从泥潭中跳出来把文章写完 再跳进去继续解决问题 问题是这样的:

  使用MS AJAX Beta + CTP新建一个项目 同时在Bin中放上Beta 的AjaxControlToolkit dll

  扔上一个Accordion 放置几个AccordionPane 设置一下CssClass

  在Page_Load中使用Page LoadControl加载一个UserControl 然后添加到页面上

  接着发现UserControl内的控件无法正常触发事件 陷入泥潭中……

  首先要说明 如果仅仅做第 步那个UserControl肯定正常运作 那意味着问题出在ScriptManager或Accordion中出现了问题

  正文

  想知道到底是什么出问题了吗?先听我说说这个ASP NET页面生命周期的问题吧

  由于生命周期按阶段划分 任务在不同阶段按部就班完成 所以我们的每一个操作都是阶段相关的 有些操作仅能在特定的阶段操作 有些操作在不同阶段执行会导致不同的结果 当然 MS希望尽量消除这些阶段间的差异 例如让一个操作在尽可能多的阶段中都能执行 并且尽可能减少在不同阶段中操作引发的不同结果 然而这不可能完全做到 例如我们都知道ViewState读写限制为仅能在某些阶段进行 于是依赖于ViewState的控件属性也就因此受到同样的限制

  控件属性读写受阶段限制 这很好接受 对吧?因为这仅仅是一层依赖关系 顺着依赖关系推广出去 情况会变得越来越复杂 限制的原因埋藏得越来越底层 接着我们发现复杂性这一问题在ASP NET这种结构良好的体系中出现了 而消灭这种复杂性的银弹还没被发明

  作为控件或组件的开发人员 我们当然有义务消除阶段差异 让下游的开发人员面对更低的复杂性 而且我们也确实尽力去做了 控件的每一层封装 都包含着这种努力 并向上承诺尽可能低的阶段差异 然而为了让控件看起来简单易用 我们不可能将这些差异完整地记录在文档之中 我们尝试去隐瞒细节 控件被层层封装时我们都这样做 底层文档没告诉我的差异 我当然也没必要写到这一层的文档上去;底层文档提及了的差异 我尽力弥补了 即使弥补得不太好 也不写到这一层的文档上去 于是文档就好像神话传说一样随着世代相传而改变 最终没有人知道这个控件依赖于某些底层的阶段差异

  做过控件开发的人都知道 有时候我们必须根据实际情况采用不同的方式构建看起来一样的控件 例如最简单的数据控件都会存在是否PostBack的构建差异 如果是非PostBack 则需要在DataBind时构建并将数据保存到ViewState 如果是PostBack则根据ViewState直接构建 如果PostBack后又遇到了DataBind则需要清除原来的构建并重新根据新数据构建 再复杂一些的控件 还会分步骤构建 默认情况下为了消除使用方的阶段差异 部分构建步骤会尽可能靠前到Init时执行 而另外一部分构建步骤则尽可能推迟到PreRender时执行 中间部分则尽可能减少自己的变化以便使用方操作 然而事情不会那么简单 使用方的某些操作(通常是访问某个属性)如果依赖于某个构建步骤的完成 因此一旦这些操作出现 原本在PreRender才执行的特定构建步骤就要提前执行 当这样的操作在不同阶段进行多几次 构建步骤就已经散落在页面生命周期的各阶段

  构建步骤可能散落于页面生命周期的各阶段对于控件设计师来说是一个严峻的问题 这意味着他要保证任何一个构建步骤在任何一个阶段执行都是无差异的 当然这不可能做到 于是又要引入别的机制来减少这种差异 复杂性就此产生了 接下来随着复杂性的增加控件设计师越来越无法确保较低的阶段差异程度 这就到控件使用者遭殃了 如果控件使用者又再把控件封装 并且依然企图降低阶段差异程度 那么灾难也就发生了……

  结果

  我花了几个小时在泥潭中泡了几个小时 边泡边写这篇文章 问题当然已经有结果了

  如果Accordion设置了HeaderCssClass或者ContentCssClass 那就会出问题 但如果为AccordionPane都加上以上两个属性 又不会有问题了 这样的情况当然通过用Reflector查看这两个类的代码来解决 结果发现Accordion会检测每一个AccordionPane是否有设置这两个属性 如果没有就把AccordionPane的设置为和自己的一样 在AccordionPane被设置时 会调用this EnsureChildControls() 这是一个会导致构建步骤提前执行的方法 于是控件构建的顺序就改变了 不仅仅Accordion内部的顺序改变了 整个Page的都改变了 由于控件的ID是按顺序自动分配的 包括我那个UserControl 构建顺序的改变意味着ID的改变 也就相当于整个控件树都改变了 事件当然不能正常触发

  最后的解决方案当然是为我那个UserControl指定ID 我花了那么多个小时才发现自己做了件蠢事 一早打开Trace来看控件树就应该能发觉UniqueID的变化

  总结

cha138/Article/program/net/201311/15217

相关参考

知识大全 面试的细节决定成败

一个无心的眼神,一个不经意的微笑,细小的动作在第一印象中,可能会决定成败。郭先生性格略显腼腆,他履历上出色的学业描述让他获得一次面试机会。面试时,当郭先生一见到考官,就紧张地垂下了眼帘。更糟糕的是,郭

知识大全 关于“细节决定成败”的议论文素材,要长点的,急需

关于“细节决定成败”的议论文素材,要长点的,急需!“一树一菩提,一沙一世界”。生活的一切原本都是由细节构成,而细节往往最容易被人忽视,殊不知这不起眼的细节,看在眼里便是风景,握在掌心便是花朵,揣在怀里

知识大全 细节动作决定面试成败

求职过程中,面试可以说是压力最大的一个环节。要想在面试中成为胜利者,要做好多方面的准备,就连一些不经意的小动作也不能忽略。美国心理学家近日指出,面试时一定要避免六个负面小动作。1.边说话边拽衣角求职者

知识大全 大学生实习细节决定成败

大学生人数多,实习机会不好找,有人好不容易过关斩将进入一家单位实习,却又不会利用难得的机会,时间花费了,却感觉没多少收获。广东ACCA(英国特许公认会计师公会)就业力大比拼比赛胜出的选手,被推荐到了广

知识大全 决定你面试成败的七大关键

危机往往是一个人在不经意间铸成的,成功也是由许多关键细节酝酿而成的。关键细节一:亮明身份考生进入考场要做的第一件事是亮出考生顺序牌,响亮的向考官问好并报出自己的面试牌号,其中最需要注意的是不得透露与本

知识大全 决定面试成败的七个关键

危机往往是一个人在不经意间铸成的,成功也是由许多关键细节酝酿而成的。关键细节一:亮明身份考生进入考场要做的第一件事是亮出考生顺序牌,响亮的向考官问好并报出自己的面试牌号,其中最需要注意的是不得透露与本

知识大全 面试决定成败的七个关键

危机往往是一个人在不经意间铸成的,成功也是由许多关键细节酝酿而成的。关键细节一:亮明身份考生进入考场要做的第一件事是亮出考生顺序牌,响亮的向考官问好并报出自己的面试牌号,其中最需要注意的是不得透露与本

知识大全 ASP.NET MVC框架Beta版技术细节

ASP.NETMVC框架Beta版技术细节  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  ASP

知识大全 细节决定命运

梅子细节是我们日常生活中容易忽略或者忽视的细微动作和情节。它虽然渺小,却往往左右著事情的成败,人生的得失。时至今日,我还清楚地记得毕业那年去某公司应征秘书一职的场景,经过层层选拔,我和一个女孩幸运地进

知识大全 ASP.NET MVC框架Beta版技术细节[3]

ASP.NETMVC框架Beta版技术细节[3]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!