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继承实现的接口:

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

几乎都是我们平常没用到的接口,不理先,我们关注IListSource怎么实现绑定的。

如果自己看一下IListSource要实现的接口有几个方法:

复制代码
public   interface  IListSource
{
    
//  Methods
    IList GetList();
    
//  Properties
     bool  ContainsListCollection {  get ; }
}
复制代码

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

复制代码
// DataTable的实现
bool  IListSource.ContainsListCollection
{
    
get  {   return   false ; }
}

IList IListSource.GetList()
{
    
return   this .DefaultView;
}
复制代码

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

复制代码
public  DataView DefaultView
{
    
get
    {
        DataView defaultView 
=   this .defaultView;
        
if  (defaultView  ==   null )
        {
            
if  ( this .dataSet  !=   null )
            {
                defaultView 
=   this .dataSet.DefaultViewManager.CreateDataView( this );
            }
            
else
            {
                defaultView 
=   new  DataView( this true );
                defaultView.SetIndex2(
"" , DataViewRowState.CurrentRows,  null true );
            }
            defaultView 
=  Interlocked.CompareExchange < DataView > ( ref   this .defaultView, defaultView,  null );
            
if  (defaultView  ==   null )
            {
                defaultView 
=   this .defaultView;
            }
        }
        
return  defaultView;
    }
}
复制代码

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

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

忽悠:

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

 

神马啊神马,没点头绪,完全找不到绑定的重点,难道说,随便找个IList返回的类就行了?

于是让MDataTable实现IListSource接口,试试看:

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

实现接口:

public  IList GetList()
{
    
return  Rows;
}

接着忽悠:

好说我的Rows也是继承自List < xxx > 的,试着绑定~~结果很飘逸,出来完全不是我想象~~
继承折腾DataView,传说DataView也能直接绑定控件的,yo~~有一丝想法

 

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

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接口,有很多方法:

复制代码
public   interface  ICustomTypeDescriptor
{
    
//  Methods
    AttributeCollection GetAttributes();
    
string  GetClassName();
    
string  GetComponentName();
    TypeConverter GetConverter();
    EventDescriptor GetDefaultEvent();
    PropertyDescriptor GetDefaultProperty();
    
object  GetEditor(Type editorBaseType);
    EventDescriptorCollection GetEvents();
    EventDescriptorCollection GetEvents(Attribute[] attributes);
    PropertyDescriptorCollection GetProperties();
    PropertyDescriptorCollection GetProperties(Attribute[] attributes);
    
object  GetPropertyOwner(PropertyDescriptor pd);
}

复制代码

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

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

复制代码
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{
    
if  ( this .dataView.Table  ==   null )
    {
        
return  zeroPropertyDescriptorCollection;
    }
    
return   this .dataView.Table.GetPropertyDescriptorCollection(attributes);
}
复制代码

继续深入:

复制代码
internal  PropertyDescriptorCollection GetPropertyDescriptorCollection(Attribute[] attributes)
{
    
if  ( this .propertyDescriptorCollectionCache  ==   null )
    {
        
int  count  =   this .Columns.Count;
        
int  num4  =   this .ChildRelations.Count;
        PropertyDescriptor[] properties 
=   new  PropertyDescriptor[count  +  num4];
        
for  ( int  i  =   0 ; i  <  count; i ++ )
        {
            properties[i] 
=   new  DataColumnPropertyDescriptor( this .Columns[i]);
        }
        
for  ( int  j  =   0 ; j  <  num4; j ++ )
        {
            properties[count 
+  j]  =   new  DataRelationPropertyDescriptor( this .ChildRelations[j]);
        }
        
this .propertyDescriptorCollectionCache  =   new  PropertyDescriptorCollection(properties);
    }
    
return   this .propertyDescriptorCollectionCache;
}

 
复制代码

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

DataColumnPropertyDescriptor是什么?继续深入:

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

两行代码,那个base是啥?是PropertyDescriptor ,实现很简单,把列名传过去就行了,至此,就结束了。

 

不知道有多少会看到这里,估计本文大伙也就是扫下来,除非某天要应用到,不然只是忽悠下眼球了。

 

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

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

 

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

 

1:MDataTable继承IListSource接口实现

复制代码
        #region  IListSource 成员
        
public   bool  ContainsListCollection
        {
            
get
            {
                
return   true ;
            }
        }
        
public  IList GetList()
        {
            
return  Rows;
        }
        
#endregion
复制代码

 

2:MDataRow继承ICustomTypeDescriptor接口实现

A:先实现自定义属性描述类

自定义属性描述类MDataProperty

 

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

复制代码
         int  index  =   0 ;
        PropertyDescriptorCollection properties;
        
public  PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            
if  (index  ==   1 )
            {
                
return  properties;
            }
            index
++ ;
            properties 
=   new  PropertyDescriptorCollection( null );

            
foreach  (MDataCell mdc  in   this )
            {
                properties.Add(
new  MDataProperty(mdc,  null ));
            }
            
return  properties;
        }
复制代码

 

OK,此至,MDataTable顺利完成了对Winform下DataGridView的支持。

 

本文原标题:CYQ.Data 轻量数据层之路 MDataTable绑定Winform之DataGridView 原理高级篇(三十一)

 

四:总结

微软很强大,MB的Silverlight不支持DataTable的绑定,难道我又要去追随?研究其绑定本质?

不追了,MDataTable增加了ToJson方法和ToList
< 实体 > 方法,可直接用json传过去再用反json系列化解析成List < 实体 > 型就可以直接绑定了。

 

 

本文有点长,不知有几人,看的明白,看的仔细,估计都是刷的一下从头拉到尾了~~~~ 

版权声明:本文原创发表于博客园,作者为路过秋天,原文链接:

http://www.cnblogs.com/cyq1162/archive/2010/10/25/1860031.html

相关实践学习
基于Hologres轻量实时的高性能OLAP分析
本教程基于GitHub Archive公开数据集,通过DataWorks将GitHub中的项⽬、行为等20多种事件类型数据实时采集至Hologres进行分析,同时使用DataV内置模板,快速搭建实时可视化数据大屏,从开发者、项⽬、编程语⾔等多个维度了解GitHub实时数据变化情况。
阿里云实时数仓实战 - 用户行为数仓搭建
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3&nbsp;)前置知识要求:熟练掌握 SQL 语法熟悉 Linux 命令,对 Hadoop 大数据体系有一定的了解 &nbsp; 课程大纲 第一章&nbsp;了解数据仓库概念 初步了解数据仓库是干什么的 第二章&nbsp;按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章&nbsp;数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章&nbsp;采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章&nbsp;用户行为数据仓库 严格按照企业的标准开发 第六章&nbsp;搭建业务数仓理论基础和对表的分类同步 第七章&nbsp;业务数仓的搭建&nbsp; 业务行为数仓效果图&nbsp;&nbsp;
相关文章
|
21天前
|
存储 域名解析 弹性计算
阿里云上云流程参考:云服务器+域名+备案+域名解析绑定,全流程图文详解
对于初次通过阿里云完成上云的企业和个人用户来说,很多用户不仅是需要选购云服务器,同时还需要注册域名以及完成备案和域名的解析相关流程,从而实现网站的上线。本文将以上云操作流程为核心,结合阿里云的活动政策与用户系统梳理云服务器选购、域名注册、备案申请及域名绑定四大关键环节,以供用户完成线上业务部署做出参考。
|
11月前
|
运维 持续交付 云计算
深入解析云计算中的微服务架构:原理、优势与实践
深入解析云计算中的微服务架构:原理、优势与实践
544 86
|
8月前
|
安全 算法 网络协议
解析:HTTPS通过SSL/TLS证书加密的原理与逻辑
HTTPS通过SSL/TLS证书加密,结合对称与非对称加密及数字证书验证实现安全通信。首先,服务器发送含公钥的数字证书,客户端验证其合法性后生成随机数并用公钥加密发送给服务器,双方据此生成相同的对称密钥。后续通信使用对称加密确保高效性和安全性。同时,数字证书验证服务器身份,防止中间人攻击;哈希算法和数字签名确保数据完整性,防止篡改。整个流程保障了身份认证、数据加密和完整性保护。
|
10月前
|
存储 缓存 算法
HashMap深度解析:从原理到实战
HashMap,作为Java集合框架中的一个核心组件,以其高效的键值对存储和检索机制,在软件开发中扮演着举足轻重的角色。作为一名资深的AI工程师,深入理解HashMap的原理、历史、业务场景以及实战应用,对于提升数据处理和算法实现的效率至关重要。本文将通过手绘结构图、流程图,结合Java代码示例,全方位解析HashMap,帮助读者从理论到实践全面掌握这一关键技术。
297 14
|
7月前
|
机器学习/深度学习 数据可视化 PyTorch
深入解析图神经网络注意力机制:数学原理与可视化实现
本文深入解析了图神经网络(GNNs)中自注意力机制的内部运作原理,通过可视化和数学推导揭示其工作机制。文章采用“位置-转移图”概念框架,并使用NumPy实现代码示例,逐步拆解自注意力层的计算过程。文中详细展示了从节点特征矩阵、邻接矩阵到生成注意力权重的具体步骤,并通过四个类(GAL1至GAL4)模拟了整个计算流程。最终,结合实际PyTorch Geometric库中的代码,对比分析了核心逻辑,为理解GNN自注意力机制提供了清晰的学习路径。
488 7
深入解析图神经网络注意力机制:数学原理与可视化实现
|
7月前
|
机器学习/深度学习 缓存 自然语言处理
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
Tiktokenizer 是一款现代分词工具,旨在高效、智能地将文本转换为机器可处理的离散单元(token)。它不仅超越了传统的空格分割和正则表达式匹配方法,还结合了上下文感知能力,适应复杂语言结构。Tiktokenizer 的核心特性包括自适应 token 分割、高效编码能力和出色的可扩展性,使其适用于从聊天机器人到大规模文本分析等多种应用场景。通过模块化设计,Tiktokenizer 确保了代码的可重用性和维护性,并在分词精度、处理效率和灵活性方面表现出色。此外,它支持多语言处理、表情符号识别和领域特定文本处理,能够应对各种复杂的文本输入需求。
839 6
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
|
8月前
|
机器学习/深度学习 算法 数据挖掘
解析静态代理IP改善游戏体验的原理
静态代理IP通过提高网络稳定性和降低延迟,优化游戏体验。具体表现在加快游戏网络速度、实时玩家数据分析、优化游戏设计、简化更新流程、维护网络稳定性、提高连接可靠性、支持地区特性及提升访问速度等方面,确保更流畅、高效的游戏体验。
191 22
解析静态代理IP改善游戏体验的原理
|
8月前
|
编解码 缓存 Prometheus
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
本期内容为「ximagine」频道《显示器测试流程》的规范及标准,我们主要使用Calman、DisplayCAL、i1Profiler等软件及CA410、Spyder X、i1Pro 2等设备,是我们目前制作内容数据的重要来源,我们深知所做的仍是比较表面的活儿,和工程师、科研人员相比有着不小的差距,测试并不复杂,但是相当繁琐,收集整理测试无不花费大量时间精力,内容不完善或者有错误的地方,希望大佬指出我们好改进!
488 16
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
|
7月前
|
传感器 人工智能 监控
反向寻车系统怎么做?基本原理与系统组成解析
本文通过反向寻车系统的核心组成部分与技术分析,阐述反向寻车系统的工作原理,适用于适用于商场停车场、医院停车场及火车站停车场等。如需获取智慧停车场反向寻车技术方案前往文章最下方获取,如有项目合作及技术交流欢迎私信作者。
454 2
|
9月前
|
机器学习/深度学习 自然语言处理 搜索推荐
自注意力机制全解析:从原理到计算细节,一文尽览!
自注意力机制(Self-Attention)最早可追溯至20世纪70年代的神经网络研究,但直到2017年Google Brain团队提出Transformer架构后才广泛应用于深度学习。它通过计算序列内部元素间的相关性,捕捉复杂依赖关系,并支持并行化训练,显著提升了处理长文本和序列数据的能力。相比传统的RNN、LSTM和GRU,自注意力机制在自然语言处理(NLP)、计算机视觉、语音识别及推荐系统等领域展现出卓越性能。其核心步骤包括生成查询(Q)、键(K)和值(V)向量,计算缩放点积注意力得分,应用Softmax归一化,以及加权求和生成输出。自注意力机制提高了模型的表达能力,带来了更精准的服务。
10358 46

热门文章

最新文章

推荐镜像

更多
  • DNS