知识大全 .NET发现之旅(二)

Posted

篇首语:怀抱观古今,寝食展戏谑。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 .NET发现之旅(二)相关的知识,希望对你有一定的参考价值。

数据绑定表达式(下):.NET发现之旅(二)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  这一节继续来谈 NET中的数据绑定表达式

  本节涉及的内容如下

  一 数据绑定方法的来源以及在低层上的实现

  二 数据绑定方法的执行效率排序

  <%#Container DataItem%><%#GetDataItem()%><%#Eval( 字段名 )%><%#DataBinder Eval(Container DataItem 字段名 )%><%#((DataRowView)Container DataItem)[ 字段名 ] %><%#((Type)Container DataItem) 成员 %><%#((Type)GetDataItem()) 成员 %>    上面七种绑定形式以及它们的变幻形式都用过吗?性能怎么排序?

  复习一下 第一节我们主要谈了数据绑定表达式的各种形式 在ASP NET页面中出现的位置 以及我们常绑定到与数据库有关的DataView DataTable DataSet 等数据源的数据绑定表达式的各种形式

  你有没有对Eval方法和DataBinder Eval方法好奇过?

  在 NET 中我们经常用Eval方法在Repeater DataList GridView等循环控件中绑定数据 Eval方法和DataBinder Eval方法在低层是怎么实现的?它们到底有什么千丝万缕的关系?

  一 来源 实现

  我们常用的Eval方法其实是Page类的一个静态单向只读方法 而且它是一个受保护的方法 实际上Page类的Eval方法是继承自TemplateControl类的 TemplateControl 类是一个抽象类 它为Page 类和 UserControl 类提供通用属性和方法 我们先来看一下继承家谱

  System Object   System Web UI Control    System Web UI TemplateControl       System Web UI Page       System Web UI UserControl    Eval方法就是TemplateControl类的方法 它有两种形式

    名称  说明  TemplateControl Eval (String)  计算数据绑定表达式  TemplateControl Eval (String String)  使用用于显示结果的指定格式字符串计算数据绑定表达式

  事实上TemplateControl类还提供了XPath方法和XPathSelect方法供Page类和UserControl继承 这 个方法是和XML数据源有关的绑定方法

  如果细心的你查看TemplateControl类的基类Control类 你就会发现其实Control类并没有提供Eval XPath XPathSelect等方法 所以Eval XPath等方法最终是在TemplateControl类中实现的

  现在 终于找到了Eval XPath等数据绑定方法的来源了

  Eval XPath等方法是 NET 新增的方法 在 NET 时代我们经常用的是DateBinder Eval方法 形如

  <%#DataBind Eval(Container DataItem 字段名 ) %>

  <%#DataBind Eval(Container DataItem 字段名 c ) %>

  Eval的出现其实就是为了简化DataBinder Eval方法的写法从而代替它

  在ASP NET 中及以上 当我们调用Eval时 Eval 方法会使用GetDataItem方法调用DataBinder Eval方法计算表达式的值 要想理解这句话 就算查边MSDN也一头雾水 除非我们知道Eval方法的源代码 否则根本找不到蛛丝马迹 这里就要用到反射了 我们通过反射获得了Eval方法的源代码

  protected   internal   object   Eval(string   expression)

  

  this CheckPageExists()

  return   DataBinder Eval(this Page GetDataItem()    expression)

  

  终于见到GetDataItem()方法了 其实它就是Page类的一个方法 也是 NET 新增一个方法 GetDataItem()方法的作用是为了获得Container DataItem 它是 NET 中用来代替Container DataItem的 如果你曾经用Repeater和DataList等绑定过数组或者ArrayList等 你就会发现<%#GetDataItem()%>和<%#Container DataItem%>等价 同时 可以肯定 Eval方法在低层上确实是调用DataBinder Eval方法实现数据绑定的 其中 this CheckPageExists() 是检查调用的时候有没有Page对象的 如果没有则会抛出一个异常

  要弄清Eval是怎么工作的 GetDataItem()方法的低层实现我们也要用反射来获取

  public object GetDataItem()

  

  if ((this _dataBindingContext == null) || (this _dataBindingContext Count == ))

  

  throw new InvalidOperationException(SR GetString( Page_MissingDataBindingContext ))

  

  return this _dataBindingContext Peek()

  

  我们从GatDataItem()方法中看到 return   this _dataBindingContext Peek() 很快就猜想_dataBindingContext是不是一个堆栈呢?事实它就是一个堆栈!通过反射查看源代码我们得出 _dataBindingContext是一个Stack类型对象 所以它有Peek方法 return   this _dataBindingContext Peek() 正是把堆栈顶部的元素返回 而if语句是用来判断这个堆栈是否已经存在或者是否已经有元素存在 如果if不成立 就会抛出一个异常

  从上面的分析我们知道 _dataBindingContext堆栈的作用是通过GetDataItem()方法这个桥梁向Eval方法提供Container DateItem 用逆向思维来理解上面这句话 Eval方法可以自动计算出Container DataItem 原因就是从dataBindingContext堆栈来获取Container DataItem 这也就为什么Eval方法能够知道形如<%#Eval 字段名 %>中字段名隶属于哪个数据项的属性的原因 同时我们也知道 NET 中的Eval在本质上的实现并没有抛弃Container DataItem 而Container DataItem在 时代也没有消失

  那么_dataBindingContext这个保存Container DataItem的堆栈是怎么建立的呢?

  我们很快就想到每次绑定控件时候最后那条语句是什么 this 控件ID DataBind() 对就是DataBind()方法 DataBind()方法还有一个重载 DataBind(bool raiseOnDataBinding) 为_dataBindingContext这个堆栈压入元素和弹出元素的方法正是用DataBind(bool flag)这个重载方法实现的

  DataBind(bool raiseOnDataBinding)在低层的实现

  protected virtual void DataBind(bool raiseOnDataBinding)            bool flag = false;//这个标志的用处在上下文中很容易推出来 如果有DataItem压栈 则在后面出栈           if (this IsBindingContainer)//判断控件是不是数据绑定容器 实际上就是判断控件类是不是实现了INamingContainer                      bool flag ;            object obj = DataBinder GetDataItem(this out   flag );//这个方法是判断控件是不是有DataItem属性 并把它取出来               if (flag && (this Page != null))//如果控件有DataItem                              this Page PushDataBindingContext(obj );//把DataItem压栈 PushDataBindingContext就是调用_dataBindingContext的Push方法                  flag = true;                            try                    if (raiseOnDataBinding)//这里是判断是不是触发DataBinding事件的                               this OnDataBinding(EventArgs Empty);                        this DataBindChildren();//对子控件进行数据绑定 如果这个控件有DataItem 则上面会将DataItem压入栈顶 这样 在子控件里面调用Eval或者GetDataItem方法 就会把刚刚压进去的DataItem给取出来                   finally                    if (flag )//如果刚才有压栈 则现在弹出来                               this Page PopDataBindingContext();//PopDataBindingContext就是调用_dataBindingContext的Pop方法                               当我们执行到this 控件ID DataBind() 时候 在低层上就会调用这个重载的方法来准备包含DataItem的_DatBindingContext堆栈

  上面的代码中提到了DataBinding事件 那么它一般什么时候被触发呢?

  1 如果用编程方式 那么在我们调用DataBind()方法时候自动触发DataBinding事件

  2 如果我们用数据源控件(例如SqlDataSource等) 当把控件绑定到数据源控件时候 这个事件就会自动触发

  一般数据绑定表达式常常放在模板中循环显示数据 例如Repeater和DataList等的模板 那么下面这个知识点应该知道 Repeater DataList FormView等控件必须使用模板 如果不使用模板 这些控件将无法显示数据 而GridView DetailsView Menu等控件也支持模板 但显示数据时不是必须的 而TreeView控件不支持模板

  注意 一般情况下 数据绑定表达式不会自动计算它的值 除非它所在的页或者控件显示调用DataBind()方法 DataBind()方法能够将数据源绑定到被调用的服务器控件及其所有子控件 同时分析并计算数据绑定表达式的值

  终于写的有点眉目了 好累!我们该回头看看Eval方法调用的静态DataBinder Eval方法在低层的实现了 我把DataBinder类的源代码作为附近提供下载

  二 执行效率

  从 一 讲述的低层实现 我们很容易来排序下面数据绑定表达式的执行效率<%#Container DataItem%><%#GetDataItem()%><%#Eval( 字段名 )%><%#DataBinder Eval(Container DataItem 字段名 )%><%#((DataRowView)Container DataItem)[ 字段名 ] %><%#((Type)Container DataItem) 成员 %><%#((Type)GetDataItem()) 成员 %>    效率最高应该是 <%#((Type)Container DataItem) 成员 %><%#Container DataItem%><%#((DataRowView)Container DataItem)[ 字段名 ] %>    效率排第二的是 <%#((Type)GetDataItem()) 成员 %><%#GetDataItem()%>    效率最低的是 <%#Eval( 字段名 )%><%#DataBinder Eval(Container DataItem 字段名 )%>    其实按上面的排序有失公允 原因是这七种数据表达绑定形式运用的场合不是完全相同的

  使用场合大概如下

   |<%#Eval( 字段名 )%><%#DataBinder Eval(Container DataItem 字段名 )%>    它们的使用场合最广 数据源可以为与数据库有关的DataSet DataTable DataView 也可以为普通集合(例如 数组 ArrayList HashTable等)和泛行集合(例如 List<T> Dictionary<Tkey Tvalue>等)

  注 它们 个永远可以相互替换 至少目前是这样 凡是可以用Eval方法的地方 就可以用DataBinder Eval方法替换 从低层实现上 Eval比DataBinder Eval方法效率稍低 原因是Eval方法对了调用GetDataItem()方法这一步 但最终都是通过DataBinder Eval方法利用反射技术根据名称查找属性 从而计算出表达式的值 所以非常影响性能

  

  <%#((DataRowView)Container DataItem)[ 字段名 ] %>

  它只能使用在数据源为与数据库有关的Dataset DatTable DataView 这些数据源都实现了IListSource接口 其实从低层实现本质上来看 它和<%#((Type)Container DataItem) 成员 %>类似

cha138/Article/program/net/201311/11866

相关参考

清心之旅

当主题旅游成为时尚的今天,和一个亦师亦友的心理医生一同上路,在淳朴、简单、纯美,甚至原始的大自然当中敞开心扉,诉说自己的心事,在轻松的旅途中接受心理医生的的疏导,排解心中困扰,这种别具特色的清心之旅已

知识大全 Eclipse 3.2冒险之旅

开源技术:Eclipse3.2冒险之旅  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!摘要:  Ec

雄激素——男子生命之旅的“总导演”

在男子生命之旅中,雄激素扮演着重要的角色,它以非凡的本领,为男子的健康效劳。雄激素赋予男子阳刚之美雄激素的家庭成员有睾酮、雄烯二酮、脱氢表雄酮等,睾酮是主力军。95%的雄激素来源于睾丸的间质细胞,5%

知识大全 走进世博课堂,体验科技之旅。 作文。急~~· 600字。

题目:走进世博课堂,体验科技之旅。作文。急~~·600字。走进世博一个阳光灿烂的星期天,我早早地做完了作业,想趁着闲暇之余干点有意义的事情,忽然从我的脑海里闪过一个好主意:2010年就要在上海举办世博

舌尖上的苦味之旅

对于中国人而言,不讲究味觉的饮食,如同未经恋爱的婚姻。正如钱钟书先生所言,中国人之吃饭,味道为至尊价值,“舌头代替了肠胃,作为最后最高的裁判”。而关于苦味食品的历史故事和传播历程,以及与之相伴相生的民

知识大全 老师要求写篇日记,我的xx之旅

老师要求写篇日记,我的xx之旅人们都说“上有天堂,下有苏杭”,我游览过春天的西湖,也观赏过夏日的西湖,还欣赏了秋色里的西湖,独独没有玩赏过冬天西湖的景致.今年的寒假,我又来到杭州,来欣赏冬日里西湖的山

知识大全 开源之旅——数据库篇(图)

  第一站 走进开源数据库    %的投入 实现%的理想    在Linux这种开放源代码的操作系统已经逐渐被越来越多的企业应用时在基础软件平台的另一端开源数据库开始显山露水    近年来美国一些大企

牛皮癣患者不妨来个“温泉之旅”

牛皮癣患者的表皮受损特别的严重,使皮肤的汗腺被堵,体内的汗液无法排出体外,所以说牛皮癣患者多出汗能够在很大程度上帮助牛皮癣患者把汗腺通开,通开之后牛皮癣癣块就会自然的脱落,所以说牛皮癣患者不妨来个“温

牛皮癣患者不妨来个“温泉之旅”

牛皮癣患者的表皮受损特别的严重,使皮肤的汗腺被堵,体内的汗液无法排出体外,所以说牛皮癣患者多出汗能够在很大程度上帮助牛皮癣患者把汗腺通开,通开之后牛皮癣癣块就会自然的脱落,所以说牛皮癣患者不妨来个“温

知识大全 .net编程之路(二)

  一枚举  如何定义枚举  例如-        PublicenumTimeOfDay  &nb