TrueLove 项目感悟(三)深入探析 Data Source Control 之一

引言

最近在做 TrueLove 项目的时候用 GridView + ObjectDataSource + NBear 的 Gateways 取得数据就能绑定到一块,按照自己的需要显示到页面上,感觉很神奇。总是想看看在这个交易之下到底有什么发生。这些数据是怎么绑定到一起的,使用了什么机制,一连串的问号。我参考了一部分 MSDN 和其他一些网站的文章,终于弄明白了真个过程,不敢独享,写下来与大家分享。

基类 BaseDataBound

所有使用新的数据源控件绑定数据的数据绑定控件都是从 BaseDataBound 这个类继承下来的。这个类有下面两个 public 的属性。

BaseDataBound 的 public 属性
virtual object DataSource  { get; set; }
virtual string DataSourceId { get; set; }

还有下面两个模板方法:

Template Methods
protected abstract void PerformSelect();
protected abstract void ValidateDataSource(object dataSource);

第一个属性 DataSource 是我在 Asp.net 1.1 时代时候绑定数据的。第二个就是我们在 Asp.net 2.0 时代用来绑定 DataSourceControl 的了。如果我们设置了 DataSource 属性之后 ValidateDataSource 方法就会被调用看绑定的数据是不是可以使用(通常判断是不是IListSource, IEnumerable 或 IDataSource 的)。

如果你在初始化阶段之后才改变 DataSourceId 属性的话,那么 DataBind 函数只有在 PreRender 的时候才能被调用,如果你在 PreRender 之后改变的话, DataBind 函数会被立即调用。有一点需要注意的是如果你在 PreLoad 之前设置 DataSourceId 的值,那么 DataBind 函数不会被调用。

下面是 BaseDataBound 类在整个 Asp.net 页面的 Life Cycle 所在的部分:

  • OnInit: 若ViewState不可用, 那么 Control 会在每次 PreRender 调用.
  • OnPreLoad: 设置一个内部标志去标识 init 阶段结束.
  • OnPreRender: 设置一个内部标识标记 PreRender 开始,并且调用 DataBind.

BaseDataBound 类拥有一个 public mothed

Public Mothed 
public override void DataBind();

这个方法会调用一个模板方法 PerformSelect,PerformSelect 方法会从下面的 DataSource 获取数据。

控件 DataBoundControl

DataBoundControl 是从 BaseDataBound 这个积累继承过来的.DataBoundControl 是所有数据绑定控件的基类。这个类比 BaseDataBound多了一个公共属性:

Public Property 
public virtual string DataMember { get; set; }

这个属性是在数据源导出多于一个数据列时确定使用那一个数据列。

这个类的主要任务是完成分离从数据源提取出来数据所衍生出来的类。这些从数据源获取的数据在模板方法 PerformDataBinding 中会被看作实现 IEnumerable 接口的派生类集合。

protected internal virtual mothed 
protected internal virtual void PerformDataBinding(IEnumerable data);

幸运的是最艰难的工作被 ConnectToDataSourceView 方法完成了。这个方法可以获取一个到 DataSourceView 的引用。对于使用 DataSourceId 的控件来说这是一个很大的进步,而对于使用 DataSource 的则需要用一个内嵌类把 DataSource 包装成一个 DataSourceControl (ReadOnlyDataSource实现了 IDataSouce 接口,返回一个只支持 Select方法的 view 对象(ReadOnlyDataSourceView))

下面是整个 DataBoundControl 在 Asp.net 页面的 Life Circle 所占的位置:

  • OnPreLoad:  如果这个页面是第一次被请求调用基类的 OnPreLoad 方法,如果 ViewState 可用但是 Control 并没有绑定数据,那么设置一个标记试图在 OnPreRender 阶段绑定数据。
  • OnLoad:  如果没有数据源的 view 则尝试获取,并且在遇到下面这种情况:如果因为某种原因导致我们在 OnPreLoad时候没有尝试绑定数据并且现在仍然没有绑定数据的,设置一个标识,让它尝试在 OnPreRender 的时候绑定数据。

我们看这个类就解决了其基类留下的在 PreLoad 之前的阶段设置 DataSourceId 属性不能自动绑定数据的问题。

如果 Control 使用 DataSourceId 属性来绑定数据,那么 Control 会在数据源变化时捕获 DataSourceView 因重新绑定control 而激活的 DataSourceViewChanged 事件(我会在后续的文章的 DataSourceView 阶段说明的)。 

这个类实现了在基类中定义的模板方法 ValidateDataSource 和 PerformSelect 。首先要先检查数据源是不是实现了 IListSource,IEnumerable 或 IDataSource 接口中的一个,如果没有就抛出异常。接着就是被 DataBind 方法调用的 PerformSelect完成下面的:

  •  如果control绑定是通过 DataSource属性则激活DataBinding事件
  •  从数据源获取 DataSourceView 
  •  使 control 绑定数据
  •  构造 select 参数,调用 DataSourceView 的 select 方法,传入一个在 select 方法执行完后会被调用的回调方法。

这个方法会在select方法执行完成后调用,在这个方法中调用了 PerformDataBinding 方法,如果还记得他就是那个传入被 IEnumerable 话的数据的方法。

关于 DataSourceControl 和 DataSourceView 的介绍我会在后续的文章中慢慢写。这篇文章主要参考了 Manuel Abadia 的文章,有一些边读边译边体会边写的味道。大家可能看着比较迷惑,我会在后续的文章中说明,并且会画出一个关系调用图。现在正在寻找画图的好工具,不知道大家有没有推荐的。

老婆今天有些感冒,很难受,希望她可以早日康复。老婆的姐姐明天去看房子叫预付款,不知道我们俩什么时候能去买房子,期待 ing ...

posted on 2007-02-06 01:46  JesseZhao  阅读(3092)  评论(3编辑  收藏  举报

导航