《上篇》主要介绍如何通过DataBinder实现批量的数据绑定,以及如何解决常见的数据绑定问题,比如数据的格式化。接下来,我们主要来谈谈DataBinder的设计,看看它是如何做到将作为数据源实体的属性值绑定到界面对应的控件上的。此外,需要特别说明一点:《上篇》中提供了DataBinder最初版本的下载,但已经和本篇文章介绍的已经大不一样了。最新版本的主要解决两个主要问题:通过Expression Tree的方式进行属性操作(属性赋值和取值),添加了“数据捕捉”(Data Capture)的功能,以实现将控件中的值赋给指定的实体。但是,这并不意味着这就是一个最终版本,这里面依然有一些问题,比如对空值的处理不不够全面,比如在进行数据绑定的时候,有的控件类型需要进行HTML Encoding,等等。[源代码从这里下载]
目录:
一、通过DataPropertyAttribute特性过滤实体的“数据属性”
二、Control/DataSource映射的表示:BindingMapping
三、如何建立Control/DataSource映射集合
四、通过映射集合实现数据绑定
五、通过映射集合实现数据捕捉
DataBinder在进行数据绑定的时候,并没有对作为数据源的对象作任何限制,也就是说任何类型的对象均可作为数据绑定的数据源。控件(这里指TextBox、Label等这样绑定标量数值的控件)绑定值来源于数据源实体的某个属性。但是一个类型的属性可能有很多,我们需要某种筛选机制将我们需要的“数据属性”提取出来。这里我们是通过在属性上应用DataPropertyAttribute一个特性来实现的。
简单起见,我不曾为DataPropertyAttribute定义任何属性成员。DataPropertyAttribute中定义了一个静态的GetDataProperties方法,得到给定实体类型的所有数据属性的名称。但是为了避免频繁地对相同实体类型进行反射,该方法对得到的属性名称数组进行了缓存。
class DataPropertyAttribute: Attribute
3: {
string[]>();
string[] GetDataProperties(Type entityType)
6: {
);
if (dataProperties.ContainsKey(entityType))
9: {
return dataProperties[entityType];
11: }
typeof(DataPropertyAttribute))
13: {
if (dataProperties.ContainsKey(entityType))
15: {
return dataProperties[entityType];
17: }
in entityType.GetProperties()
true).Any()
20: select property.Name).ToArray();
21: dataProperties[entityType] = properties;
return properties;
23: }
24: }
25: }