网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 设计资源 > .Net编程 > 正文

DataTable深入解析数据源绑定原理之高级篇

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务

只是人各有看法,当我写出一篇文章时,我只是希望:

1:如果你还不懂,请看写法,了解想法。
2:如果你已懂,略过写法,请看想法。

  其实纵观我一直写来的200多篇文章,基本都可以看出那么点痕迹:

一:没有水文。
二:没有华丽理论型的文章。
三:实战型文章很多。
四:文章尽量面向新手的表述,尽量了。

  一、Winform下的DataGridView不支持使用DataReader绑定

  1:问题产生

在 CYQ.Data 框架 进行到V1.5版本要支持Winform时,曾遇到一个问题,就是无法绑定DataGridView。

  2:思考分析试验

MDataTable走的是DataReader方式实现的绑定,除非DataReader无法绑定DataGridView,不然就是自己实现有问题。
因此,做个试验:使用SqlDataReader直接绑定Winform下的DataGridView,发现失败了。
于是大量搜索,发现DataReader实在无法直接绑定DataGridView,通过数据源控件中转绑定的就算了。

  3:得出结论

DataReader方式都无法绑定Winform下的DataGridView,我这继承之DataReader的实现方式也就更无从实现绑定了。
只好另寻方法-》DataGridView支持DataTable,于是要从DataTable入手了。

  二、DataTable很强大,支持Web又支持Winform

  1:分析绑定原理

在以前的MDataTable实现绑定原理篇中,我们研究出要实现绑定,有两种方式:
一种是实现IEnumerable接口,即当初走的DataReader方式实现的绑定。
另一种是实现IListSource接口,即走DataTable方式实现的绑定。
为啥当初不实现DataTable方式的绑定,不就完了,两种都支持~~-_-..现在又得回去折腾IListSource接口的实现。

  2:深入DataTable绑定原理

  我们通过Reflector反编绎看下DataTable继承实现的接口:

  1. public class DataTable : MarshalByValueComponent, IListSource, ISupportInitializeNotification, ISupportInitialize, ISerializable, IXmlSerializable 

几乎都是我们平常没用到的接口,不理先,我们关注IListSource怎么实现绑定的。如果自己看一下IListSource要实现的接口有几个方法:

  1. public interface IListSource 
  2.     // Methods 
  3.     IList GetList(); 
  4.     // Properties 
  5.     bool ContainsListCollection { get; } 

就两个,太容易了,接着我们要在DataTable 6000多行的代码中找到IListSource的实现,查找是最好的方法

  1. //DataTable的实现 
  2. bool IListSource.ContainsListCollection 
  3.     get {  return false; } 
  4.  
  5. IList IListSource.GetList() 
  6.     return this.DefaultView; 

GetList接口没事就返回了个默认视图,又要切进去看视图了。

  1. public DataView DefaultView 
  2.     get 
  3.     { 
  4.         DataView defaultView = this.defaultView; 
  5.         if (defaultView == null
  6.         { 
  7.             if (this.dataSet != null
  8.             { 
  9.                 defaultView = this.dataSet.DefaultViewManager.CreateDataView(this); 
  10.             } 
  11.             else 
  12.             { 
  13.                 defaultView = new DataView(thistrue); 
  14.                 defaultView.SetIndex2("", DataViewRowState.CurrentRows, nulltrue); 
  15.             } 
  16.             defaultView = Interlocked.CompareExchange<DataView>(ref this.defaultView, defaultView, null); 
  17.             if (defaultView == null
  18.             { 
  19.                 defaultView = this.defaultView; 
  20.             } 
  21.         } 
  22.         return defaultView; 
  23.     } 

切进去就一大堆,实在没心情看下去,省略中间看个头与尾,只知道返回了个DataView。

  1. public class DataView : MarshalByValueComponent, IBindingListView, IBindingList, IList, ICollection, IEnumerable, ITypedList, ISupportInitializeNotification, ISupportInitialize 

 

忽悠:

又是神马般的一堆接口,内部代码太多,实在没心情看;
我只想知道IListSource怎么实现绑定,至于其它有一堆没一堆的我根本不关心,我只要我想要的。
扫了一眼接口,发现是继承了IList,这和IListSource要求的返回值IList是一致的。

  神马啊神马,没点头绪,完全找不到绑定的重点,难道说,随便找个IList返回的类就行了?于是让MDataTable实现IListSource接口,试试看:

 

  1. public class MDataTable : IDataReader, IEnumerable,System.ComponentModel.IListSource 

 

实现接口:

 

  1. public IList GetList() 
  2.     return Rows; 

 

接着忽悠:

好说我的Rows也是继承自List<xxx>的,试着绑定~~结果很飘逸,出来完全不是我想象~~。

继承折腾DataView,传说DataView也能直接绑定控件的,yo~~有一丝想法。

于是看一下其实现IList接口的源码,发现一堆都在操作DataRowView

 

  1. public class DataRowView : ICustomTypeDescriptor, IEditableObject, IDataErrorInfo, INotifyPropertyChanged 

 

没法忽悠了:

你个XX,从DataTable-》DataView-》DataRowView,再转我头就晕了~~。
又是一堆很陌生的接口,于是到这里,我几乎停止了脚步,因为我分析不下去了~~。

 上WC仔细从头想过:

  对于IList<实体>绑定,所有的属性都会被认为是列名,其值为行的值。而对于DataTable,里面又是怎么认识出列名和分析出值的呢?

1:从DataTable中,我们看到一丝列名提取的相关方法,只是返回->DataRow。
2:从DataRow中也看不到提取列名的方法,其关键性的IList接口的相关实现引出了->DataRowView。
3:DataRowView?是神秘的所在?一堆继承的接口也是很陌生。

回头继续搜索:

  转换思路继续大量搜索:换了很多关键字,搜中文又搜E文。结果尽是一堆自定义控件开发的东东,结果印象中在某一篇的googleE文的“网页快照”中发现一段E文,原文不知是哪了,上次都记得只能打开快照,现在估计能快照都没了,按想象翻译出来的中文大致为:

DataTable能实现其绑定,是因为其实现了ICustomTypeDescriptor,从而获得其属性。

 

 偶滴神啊~能从千军万马的E文中,扫到几个关键字不容易啊!!!

如果回过头看上面的DataRowView,就会发现,正好,它实现了接口ICustomTypeDescriptor,
只是遥想当年,我并不像现在写文这么冷静,我当初早把Reflector关掉了,哪还记得DataRowView实现了ICustomTypeDescriptor,
再说ICustomTypeDescriptor对我又是那么的陌生,是那么的陌生,很陌生。。。

 

秘密已经出来了:

ICustomTypeDescriptor接口,一个移动控件开发人员经常打交道的接口,对于我们却极为陌生的接口。
是它,就是它,就是它实现如何识别哪些是列名,哪些是列值。

  3:浅入ICustomTypeDescriptor 

当初我通过大量的搜索,试图找到相关的应用示例,因为那时我不知道DataRowView,要是知道,我就不用那么辛苦去搜文章了。
如果你搜索此接口,你会发现一堆的文章都是说移动控件开发,我就是从移动控件开发中很辛苦的挖了点示例实现了。

  不过此文就不走弯路了,直接分析DataRowView,对于 ICustomTypeDescriptor接口,有很多方法: 

  1. public interface ICustomTypeDescriptor 
  2.     // Methods 
  3.     AttributeCollection GetAttributes(); 
  4.     string GetClassName(); 
  5.     string GetComponentName(); 
  6.     TypeConverter GetConverter(); 
  7.     EventDescriptor GetDefaultEvent(); 
  8.     PropertyDescriptor GetDefaultProperty(); 
  9.     object GetEditor(Type editorBaseType); 
  10.     EventDescriptorCollection GetEvents(); 
  11.     EventDescriptorCollection GetEvents(Attribute attributes); 
  12.     PropertyDescriptorCollection GetProperties(); 
  13.     PropertyDescriptorCollection GetProperties(Attribute attributes); 
  14.     object GetPropertyOwner(PropertyDescriptor pd); 

 

不过基本是摆设,只因用不到,除了一个接口方法:GetProperties(Attribute attributes)

  于是我们分析DataRowView对此接口的实现:

  1. PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute attributes) 
  2.     if (this.dataView.Table == null
  3.     { 
  4.         return zeroPropertyDescriptorCollection; 
  5.     } 
  6.     return this.dataView.Table.GetPropertyDescriptorCollection(attributes); 

继续深入:

  1. internal PropertyDescriptorCollection GetPropertyDescriptorCollection(Attribute attributes) 
  2.     if (this.propertyDescriptorCollectionCache == null
  3.     { 
  4.         int count = this.Columns.Count; 
  5.         int num4 = this.ChildRelations.Count; 
  6.         PropertyDescriptor properties = new PropertyDescriptor[count + num4]; 
  7.         for (int i = 0; i < count; i++) 
  8.         { 
  9.             properties[i] = new DataColumnPropertyDescriptor(this.Columns[i]); 
  10.         } 
  11.         for (int j = 0; j < num4; j++) 
  12.         { 
  13.             properties[count + j] = new DataRelationPropertyDescriptor(this.ChildRelations[j]); 
  14.         } 
  15.         this.propertyDescriptorCollectionCache = new PropertyDescriptorCollection(properties); 
  16.     } 
  17.     return this.propertyDescriptorCollectionCache; 

 

关键定位,只是返回一组:DataColumnPropertyDescriptor 。

  那DataColumnPropertyDescriptor是什么?继续深入:

  1. internal DataColumnPropertyDescriptor(DataColumn dataColumn) : base(dataColumn.ColumnName, null
  2.     this.column = dataColumn; 

 

两行代码,那个base是啥?是PropertyDescriptor ,实现很简单,把列名传过去就行了,至此,就结束了。不知道有多少会看到这里,估计本文大伙也就是扫下来,除非某天要应用到,不然只是忽悠下眼球了。

  总结下具体实现ICustomTypeDescriptor接口方法:

1:继承实现接口方法。
2:重点实现GetProperties(Attribute attributes)方法。
3:需要自定义属性描述类,而这自定义的属性描述类需要继承自抽象基类PropertyDescriptor。
4:GetProperties返回的是自定义属性描述类的集合。

  三、绑定原理分析完,MDataTable模仿出击

  1:MDataTable继承IListSource接口实现

  1. #region IListSource 成员 
  2.   public bool ContainsListCollection 
  3.   { 
  4.       get 
  5.       { 
  6.           return true
  7.       } 
  8.   } 
  9.   public IList GetList() 
  10.   { 
  11.       return Rows; 
  12.   } 
  13.   #endregion 

2:MDataRow继承ICustomTypeDescriptor接口实现
  A:先实现自定义属性描述类

自定义属性描述类MDataProperty

  1. internal class MDataProperty : System.ComponentModel.PropertyDescriptor 
  2.     { 
  3.         private MDataCell cell = null
  4.         public MDataProperty(MDataCell mdc, Attribute attrs) 
  5.             : base(mdc._CellStruct.ColumnName, attrs) 
  6.         { 
  7.             cell = mdc; 
  8.         } 
  9.  
  10.         public override bool CanResetValue(object component) 
  11.         { 
  12.             return false
  13.         } 
  14.  
  15.         public override Type ComponentType 
  16.         { 
  17.             get 
  18.             { 
  19.                 return typeof(MDataCell); 
  20.             } 
  21.         } 
  22.         public override object GetValue(object component) 
  23.         { 
  24.             return ((MDataRow)component)[cell._CellStruct.ColumnName].Value; 
  25.             
  26.         } 
  27.  
  28.         public override bool IsReadOnly 
  29.         { 
  30.             get 
  31.             { 
  32.                 return false
  33.             } 
  34.         } 
  35.  
  36.         public override Type PropertyType 
  37.         { 
  38.             get { return cell._CellStruct.ValueType; } 
  39.         } 
  40.  
  41.         public override void ResetValue(object component) 
  42.         { 
  43.  
  44.         } 
  45.  
  46.         public override void SetValue(object component, object value) 
  47.         { 
  48.             cell.Value = value; 
  49.         } 
  50.  
  51.         public override bool ShouldSerializeValue(object component) 
  52.         { 
  53.             return true
  54.         } 
  55.                
  56.         public override bool IsBrowsable 
  57.         { 
  58.             get 
  59.             { 
  60.                 return true
  61.             } 
  62.         } 
  63.     } 

B:实现重点方法GetProperties(Attribute attributes)

  1. int index = 0; 
  2.         PropertyDescriptorCollection properties; 
  3.         public PropertyDescriptorCollection GetProperties(Attribute attributes) 
  4.         { 
  5.             if (index == 1) 
  6.             { 
  7.                 return properties; 
  8.             } 
  9.             index++; 
  10.             properties = new PropertyDescriptorCollection(null); 
  11.  
  12.             foreach (MDataCell mdc in this
  13.             { 
  14.                 properties.Add(new MDataProperty(mdc, null)); 
  15.             } 
  16.             return properties; 
  17.         } 

 

 OK,此至,MDataTable顺利完成了对Winform下DataGridView的支持。本文原标题:CYQ.Data 轻量数据层之路 MDataTable绑定Winform之DataGridView 原理高级篇(三十一)

  四、总结

微软很强大,MB的Silverlight不支持DataTable的绑定,难道我又要去追随?研究其绑定本质?
不追了,MDataTable增加了ToJson方法和ToList<实体>方法,可直接用json传过去再用反json系列化解析成List<实体>型就可以直接绑定了。
  • 上一篇资讯: asp.net缓存
  • 设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
    版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
    Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师