自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一句代碼實現(xiàn)批量數(shù)據(jù)綁定 下

數(shù)據(jù)庫
《上篇》主要介紹如何通過DataBinder實現(xiàn)批量的數(shù)據(jù)綁定,以及如何解決常見的數(shù)據(jù)綁定問題,比如數(shù)據(jù)的格式化。接下來,我們主要來談?wù)凞ataBinder的設(shè)計,看看它是如何做到將作為數(shù)據(jù)源實體的屬性值綁定到界面對應(yīng)的控件上的。

《上篇》主要介紹如何通過DataBinder實現(xiàn)批量的數(shù)據(jù)綁定,以及如何解決常見的數(shù)據(jù)綁定問題,比如數(shù)據(jù)的格式化。接下來,我們主要來談?wù)凞ataBinder的設(shè)計,看看它是如何做到將作為數(shù)據(jù)源實體的屬性值綁定到界面對應(yīng)的控件上的。此外,需要特別說明一點:《上篇》中提供了DataBinder最初版本的下載,但已經(jīng)和本篇文章介紹的已經(jīng)大不一樣了。***版本的主要解決兩個主要問題:通過Expression Tree的方式進(jìn)行屬性操作(屬性賦值和取值),添加了“數(shù)據(jù)捕捉”(Data Capture)的功能,以實現(xiàn)將控件中的值賦給指定的實體。但是,這并不意味著這就是一個最終版本,這里面依然有一些問題,比如對空值的處理不不夠全面,比如在進(jìn)行數(shù)據(jù)綁定的時候,有的控件類型需要進(jìn)行HTML Encoding,等等。

目錄:

  1. 通過DataPropertyAttribute特性過濾實體的“數(shù)據(jù)屬性”
  2. Control/DataSource映射的表示:BindingMapping
  3. 如何建立Control/DataSource映射集合
  4. 通過映射集合實現(xiàn)數(shù)據(jù)綁定
  5. 通過映射集合實現(xiàn)數(shù)據(jù)捕捉

#p#

一、通過DataPropertyAttribute特性過濾實體的數(shù)據(jù)屬性

DataBinder在進(jìn)行數(shù)據(jù)綁定的時候,并沒有對作為數(shù)據(jù)源的對象作任何限制,也就是說任何類型的對象均可作為數(shù)據(jù)綁定的數(shù)據(jù)源??丶ㄟ@里指TextBox、Label等這樣綁定標(biāo)量數(shù)值的控件)綁定值來源于數(shù)據(jù)源實體的某個屬性。但是一個類型的屬性可能有很多,我們需要某種篩選機制將我們需要的“數(shù)據(jù)屬性”提取出來。這里我們是通過在屬性上應(yīng)用DataPropertyAttribute一個特性來實現(xiàn)的。

簡單起見,我不曾為DataPropertyAttribute定義任何屬性成員。DataPropertyAttribute中定義了一個靜態(tài)的GetDataProperties方法,得到給定實體類型的所有數(shù)據(jù)屬性的名稱。但是為了避免頻繁地對相同實體類型進(jìn)行反射,該方法對得到的屬性名稱數(shù)組進(jìn)行了緩存。

  1. [AttributeUsage( AttributeTargets.Property, AllowMultiple = false,Inherited = true)]  
  2.  public class DataPropertyAttribute: Attribute  
  3.  {  
  4.      private static Dictionary<Type, string[]> dataProperties = new Dictionary<Type, string[]>();  
  5.      public static string[] GetDataProperties(Type entityType)  
  6.      {  
  7.          Guard.ArgumentNotNullOrEmpty(entityType, "entityType");  
  8.          if (dataProperties.ContainsKey(entityType))  
  9.          {  
  10.              return dataProperties[entityType];  
  11.          }  
  12.          lock (typeof(DataPropertyAttribute))  
  13.          {  
  14.              if (dataProperties.ContainsKey(entityType))  
  15.              {  
  16.                  return dataProperties[entityType];  
  17.              }  
  18.              var properties = (from property in entityType.GetProperties()  
  19.                                where property.GetCustomAttributes(typeof(DataPropertyAttribute), true).Any()  
  20.                                select property.Name).ToArray();  
  21.              dataProperties[entityType] = properties;  
  22.              return properties;  
  23.          }  
  24.      }  
  25.  }  

 #p#

二、Control/DataSource映射的表示:BindingMapping

不論是數(shù)據(jù)綁定(實體=〉控件),還是數(shù)據(jù)捕捉(控件=〉實體)的實現(xiàn)都建立在兩種之間存在著某種約定的映射之上,這個映射是整個DataBinder的核心所在。在這里,我定義了如下一個BindingMapping類型表示這個映射關(guān)系。

  1. public class BindingMapping: ICloneable  
  2. {  
  3.     public Type DataSourceType { get; private set; }  
  4.     public Control Control { get; set; }  
  5.     public string ControlValueProperty { get; set; }  
  6.     public string DataSourceProperty { get; set; }  
  7.     public bool AutomaticBind { get; set; }  
  8.     public bool AutomaticUpdate { get; set; }  
  9.     public string FormatString { get; set; }  
  10.     public Type ControlValuePropertyType  
  11.     {  
  12.         get { return PropertyAccessor.GetPropertyType(this.Control.GetType(), this.ControlValueProperty); }  
  13.     }  
  14.     public Type DataSourcePropertyType  
  15.     {  
  16.         get { return PropertyAccessor.GetPropertyType(this.DataSourceType, this.DataSourceProperty); }  
  17.     }  
  18.      
  19.     public BindingMapping(Type dataSourceType, Control control, string controlValueProperty, string dataSourceProperty)  
  20.     {  
  21.          //...  
  22.         this.DataSourceType         = dataSourceType;  
  23.         this.Control                = control;  
  24.         this.ControlValueProperty   = controlValueProperty;  
  25.         this.DataSourceProperty     = dataSourceProperty;  
  26.         this.AutomaticBind          = true;  
  27.         this.AutomaticUpdate        = true;  
  28.     }  
  29.     object ICloneable.Clone()  
  30.     {  
  31.         return this.Clone();  
  32.     }  
  33.     public BindingMapping Clone()  
  34.     {  
  35.         var bindingMapping = new BindingMapping(this.DataSourceType, this.Control, this.ControlValueProperty, this.DataSourceProperty);  
  36.         bindingMapping.AutomaticBind = this.AutomaticBind;  
  37.         bindingMapping.AutomaticUpdate = this.AutomaticBind;  
  38.         return bindingMapping;  
  39.     }  
  40. }  

這里我主要介紹一下各個屬性的含義:

DataSourceType:作為數(shù)據(jù)源實體的類型;

Control:需要綁定的控件;

ControlValueProperty:數(shù)據(jù)需要綁定到控件屬性的名稱,比如TextBox是Text屬性,而RadioButtonList則是SelectedValue屬性;

DataSourceProperty:實體類型中的數(shù)據(jù)屬性名稱

AutomaticBind:是否需要進(jìn)行自動綁定,通過它阻止不必要的自動數(shù)據(jù)綁定行為。默認(rèn)值為True,如果改成False,基于該條映射的綁定將被忽略;

AutomaticUpdate:是否需要進(jìn)行自動更新到數(shù)據(jù)實體中,通過它阻止不必要的自動數(shù)據(jù)捕捉行為。默認(rèn)值為True,如果改成False,基于該條映射的數(shù)據(jù)捕捉定將被忽略;

FormatString:格式化字符串;

ControlValuePropertyType:控件綁定屬性的類型,比如TextBox的綁定屬性為Text,那么ControlValuePropertyType為System.String;

DataSourcePropertyType:實體屬性類型。

需要補充一點的是:ControlValuePropertyType和DataSourcePropertyType使用到了之前定義的用于操作操作屬性的組件ProcessAccessor。BindingMapping采用了克隆模式。

#p#

三、如何建立Control/DataSource映射集合

BindingMapping表示的一個實體類型的數(shù)據(jù)屬性和具體控件之間的映射關(guān)系,而這種關(guān)系在使用過程中是以批量的方式進(jìn)行創(chuàng)建的。具體來說,我們通過指定實體類型和一個作為容器的空間,如果容器中的存在滿足映射規(guī)則的子控件,相應(yīng)的映射會被創(chuàng)建。映射的批量創(chuàng)建是通過DataBinder的靜態(tài)方法BuildBindingMappings來實現(xiàn)的。

在具體介紹BuildBindingMappings方法之前,我們需要先來討論一個相關(guān)的話題:在進(jìn)行數(shù)據(jù)綁定的時候,如何決定數(shù)據(jù)應(yīng)該賦值給控件的那個屬性。我們知道,不同的控件類型擁有不同的數(shù)據(jù)綁定屬性,比如TextBox自然是Text屬性,CheckBox則是Checked屬性。ASP.NET在定義控件類型的時候,采用了一個特殊性的特性ControlValuePropertyAttribute來表示那個屬性表示的是控件的“值”。比如TextBox和CheckBox分別是這樣定義的。

  1. [ControlValueProperty("Text")]  
  2. public class TextBox : WebControl, IPostBackDataHandler, IEditableTextControl, ITextControl  
  3. {  
  4.     //...  
  5. }  
  6.     
  7. ControlValueProperty("Checked")]  
  8. public class CheckBox : WebControl, IPostBackDataHandler, ICheckBoxControl  
  9. {  
  10.     //...  
  11. }  

在這里我們直接將ControlValuePropertyAttribute中指定的名稱作為控件綁定的屬性名,即BindingMapping的ControlValueProperty屬性。該值得獲取通過如下一個GetControlValuePropertyName私有方法完成。為了避免重復(fù)反射操作,這里采用了全局緩存。

  1. private static string GetControlValuePropertyName(Control control)  
  2. {  
  3.     if (null == control)  
  4.     {  
  5.         return null;  
  6.     }  
  7.     Type entityType = control.GetType();  
  8.     if (controlValueProperties.ContainsKey(entityType))  
  9.     {  
  10.         return controlValueProperties[entityType];  
  11.     }  
  12.     lock (typeof(DataBinder))  
  13.     {  
  14.         if (controlValueProperties.ContainsKey(entityType))  
  15.         {  
  16.             return controlValueProperties[entityType];  
  17.         }  
  18.         ControlValuePropertyAttribute controlValuePropertyAttribute = (ControlValuePropertyAttribute)entityType.GetCustomAttributes(typeof(ControlValuePropertyAttribute), true)[0];  
  19.         controlValueProperties[entityType] = controlValuePropertyAttribute.Name;  
  20.         return controlValuePropertyAttribute.Name;  
  21.     }  
  22. }  

最終的映射通過如下定義的BuildBindingMappings方法來建立,缺省參數(shù)suffix代表的是控件的后綴,其中已經(jīng)在《上篇》介紹過了。

  1. public static IEnumerable<BindingMapping> BuildBindingMappings(Type entityType, Control container, string suffix = "")  
  2. {  
  3.     //...  
  4.     suffixsuffix = suffix??string.Empty;  
  5.     return (from property in DataPropertyAttribute.GetDataProperties(entityType)  
  6.             let control = container.FindControl(string.Format("{1}{0}", suffix, property))  
  7.             let controlValueProperty = GetControlValuePropertyName(control)  
  8.             where null != control  
  9.             select new BindingMapping(entityType, control, controlValueProperty, property)).ToArray();  
  10. }  

#p#

四、通過映射集合實現(xiàn)數(shù)據(jù)綁定

通過《上篇》我們知道,DataBinder提供兩種數(shù)據(jù)綁定方式:一種是直接通過傳入數(shù)據(jù)實體對象和容器控件對具有匹配關(guān)系的所有子控件進(jìn)行綁定;另外一種則是通過調(diào)用上面BuildBindingMappings靜態(tài)方法建立的BindingMapping集合,然后再借助于這個集合進(jìn)行數(shù)據(jù)綁定。這兩種方式的數(shù)據(jù)綁定對應(yīng)于如下兩個重載的BindData方法:

  1. public class DataBinder  
  2. {  
  3.     //...  
  4.     public void BindData(object entity, Control container, string suffix = "");  
  5.     public void BindData(object entity,IEnumerable<BindingMapping> bindingMappings);  
  6. }  

已經(jīng)上在內(nèi)部,上面一個方法也是需要通過調(diào)用BuildBindingMappings來建立映射。數(shù)據(jù)綁定始終是根據(jù)BindingMapping集合進(jìn)行的。由于在BindingMapping中已經(jīng)定義了完成數(shù)據(jù)綁定所需的必要信息,數(shù)據(jù)綁定的邏輯變得很簡單。具體來說,數(shù)據(jù)綁定的邏輯是這樣的:遍歷所有的集合中每個BindingMapping,根據(jù)DataSourceProperty得到屬性名稱,然后進(jìn)一步從數(shù)據(jù)源實體中得到具體的值。根據(jù)ControlValuePropertyType得到目標(biāo)控件綁定屬性的類型,然后將之前得到的值轉(zhuǎn)換成該類型。***,通過ControlValueProperty得到控件的綁定屬性,將之前經(jīng)過轉(zhuǎn)換的值給控件的這個屬性就可以了。整個數(shù)據(jù)綁定實現(xiàn)在如下一個OnBindData方法中。關(guān)于屬性操作則借助于PropertyAccessor這個組件。

  1. protected virtual void OnBindData(IEnumerable<BindingMapping> bindingMappings, object entity)  
  2. {  
  3.     foreach (var mapping in bindingMappings)  
  4.     {  
  5.         var bindingMapping = mapping.Clone();  
  6.         object value = PropertyAccessor.Get(entity, bindingMapping.DataSourceProperty);  
  7.         if (null != this.DataItemBinding)  
  8.         {  
  9.             var args = new DataBindingEventArgs(bindingMapping, value);  
  10.             this.DataItemBinding(this, args);  
  11.             value = args.DataValue;  
  12.         }  
  13.         if (!bindingMapping.AutomaticBind)  
  14.         {  
  15.             continue;  
  16.         }  
  17.    
  18.         if (!string.IsNullOrEmpty(bindingMapping.FormatString))  
  19.         {  
  20.             value = Format(value, bindingMapping.FormatString);  
  21.         }  
  22.           
  23.         Type controlValuePropertyType = PropertyAccessor.GetPropertyType(bindingMapping.Control.GetType(), bindingMapping.ControlValueProperty);  
  24.         value = ChangeType(value, controlValuePropertyType);  
  25.         if (null == value && typeof(ValueType).IsAssignableFrom(controlValuePropertyType))  
  26.         {  
  27.             value = Activator.CreateInstance(controlValuePropertyType);  
  28.         }  
  29.         PropertyAccessor.Set(bindingMapping.Control, bindingMapping.ControlValueProperty, value);  
  30.         if (null != this.DataItemBound)  
  31.         {  
  32.             this.DataItemBound(this, new DataBindingEventArgs(bindingMapping, value));  
  33.         }  
  34.     }  
  35. }  

DataBinder設(shè)計的目標(biāo)是讓默認(rèn)的綁定行為解決80%的問題,并且提供給相應(yīng)的方式去解決余下的問題。為了讓開發(fā)者能夠有效解決余下的這20%的綁定問題,我們定義兩個事件:DataItemBinding和DataBound,它們分別在進(jìn)行綁定之前和之后被觸發(fā)。關(guān)于事件的觸發(fā),已經(jīng)體現(xiàn)在OnBindData方法的定義中了。

#p#

五、通過映射集合實現(xiàn)數(shù)據(jù)捕捉

數(shù)據(jù)綁定使用到的實際上是Entity-〉Control映射,如果我們借助控件到Control-〉Entity,就能實現(xiàn)自動捕獲控件的值然后將其保存到給定的實體對象上。我為此在DataBinder上定義了兩個重載的UpdateData方法。

  1. public class DataBinder  
  2. {  
  3.     //...  
  4.     public void BindData( object entity,IEnumerable<BindingMapping> bindingMappings);  
  5.     public void UpdateData( object entity, Control container, string suffix = "");  
  6. }  

UpdateData方法的實現(xiàn)和BindData方法的邏輯基本一致,將Control和Entity呼喚一下而已,所以在這里我就不再贅言敘述了。
 

原文鏈接:http://www.cnblogs.com/artech/archive/2011/03/27/databinding2.html

【編輯推薦】

  1. DBA應(yīng)用技巧:如何升級InnoDB Plugin
  2. 一句代碼實現(xiàn)批量數(shù)據(jù)綁定[上篇]
  3. DBA必備:MySQL數(shù)據(jù)庫常用操作和技巧
  4. MySQL日志操作教程:DBA們管理的利器
  5. MySQL觸發(fā)器如何正確使用

 

責(zé)任編輯:艾婧 來源: 博客園
相關(guān)推薦

2011-03-24 10:24:45

批量數(shù)據(jù)綁定

2012-02-09 09:41:22

2023-11-06 08:31:58

業(yè)務(wù)代碼多線程

2021-05-11 15:34:04

Task.Result代碼Winform

2013-03-22 10:53:42

PyConPython

2011-06-13 09:25:01

斷號

2009-03-10 18:10:12

LinuxUbuntu技巧

2023-07-12 08:01:28

FOADMROADMOXC

2021-12-17 08:55:26

Python微博機器人

2019-11-15 18:00:18

MySQLSQL數(shù)據(jù)庫

2013-05-10 10:56:09

2023-09-05 23:34:52

Kubernetes云原生

2009-10-29 09:57:16

VB.NET實現(xiàn)數(shù)據(jù)綁

2015-08-03 10:21:04

設(shè)計模式表達(dá)

2020-11-27 09:57:11

Python代碼PyPy

2022-08-01 10:01:11

JavaScript語言代碼庫

2014-12-16 08:58:17

甲骨文Oracle數(shù)據(jù)庫選件

2025-03-13 11:09:47

2016-09-12 15:26:06

戴爾

2023-08-25 17:10:14

LLM人工智能
點贊
收藏

51CTO技術(shù)棧公眾號