首页 / 软件开发 / C# / C#发现之旅第十一讲 使用反射和特性构造自己的ORM框架(上)
C#发现之旅第十一讲 使用反射和特性构造自己的ORM框架(上)2011-04-27 cnblogs 袁永福ORM背景在数据库界,主流的数据库都是关系型数据库,其采用的关系型数据结构模型,无论从数学上还是实践中都相当的成熟,得到非常广泛的应用。在关系型数据结构理论中,所有的数据都组织成一个个相互独立的二维表格,一个数据表有若干行若干列。因此关系型数据库适合存储大量的结构简单的数据,不适合存储复杂的数据结构。在编程界,面向对象的编程思想及其派生思想占据主流。面向对象的编程思想具有封装,继承,重载等手段来方便的实现比较复杂的数据结构,这适应了现代信息系统包含大量复杂数据结构的特点。因此面向对象的编程思想得到广泛应用。关系型数据模型和面向对象的编程思想之间存在比较大的差别,数据在两者之间的交换是不大通畅的,就像南京,江北和主城区之间是长江来阻断交通。因此开发人员迫切需要破解这种数据交通的阻断。以前程序员需要编程,从数据库中读取一个个字段值并赋值到编程对象的一个个字段或属性上,这就像在长江上架一个独木桥,开发效率低下,维护困难。后来出现一种叫ORM的框架性的程序,它能根据某些配置信息将数据库中的字段和编程对象的字段或属性之间建立映射关系,从而能方便的从数据库读取字段值并赋值到对象属性中。这是一种半自动的机制,能比较大的提高开发效率,简化维护,这就像在长江上架设了一座高速公路大桥。从本质上说,关系型数据库和面向对象的编程思想之间的隔阂非常大,就像长江是天涧,即使建五六座大桥也不够用。彻底的解决方法就是抛弃关系型数据库而使用面向对象的数据库,不过这个过程就像南京江北整体搬迁到江南一样,工程浩大,时间漫长。在等待面向对象数据库的统治前,我们仍然得忍受关系型数据库和面向对象编程思想之间的数据交通不畅的痛苦,并使用ORM框架来很有限的降低这种痛苦。从这个角度上说,我们痛恨关系型数据库,就像搞运载火箭的人痛恨地球引力一样。反射和特性反射是.NET框架提供的一种高级编程接口。学过VB的都知道VB中有一个CallByName函数,它能调用对象的指定名称的成员方法,比如有个窗体对象,我们可以调用“frm.Close()”来关闭窗体,也可以调用“CallByName( frm , “Close”)”来实现同样的功能。而反射就是CallByName的.NET版本,而且功能更加强大。使用反射,我们可以列出任何对象类型的所有的字段,属性,方法和事件的名称,包括公开的或私有的。我们还可以更深入的获得字段的数据类型,成员方法的参数的个数,类型及其返回值;事件使用的委托类型等等。可以说反射技术就是.NET框架提供的只读的程序基因分析技术。.NET框架对反射这种程序基因分析技术提供了天然的支持。在.NET框架中,任何对象类型都是从object类型上面派生的,object类型有一个GetType函数,该函数返回一个System.Type类型的对象,该对象就是反射操作的入口点,这样任何.NET对象类型都能用反射技术进行分析。特性也是.NET框架提供的一种高级编程手段。它是附加在类型,字段,属性,函数等编程单元上面的额外信息,就相当于Access数据库中的表和字段的说明文本。它不会影响所附着的编程单元的正常执行。但它是客观存在的,可以通过反射来获得其信息,一般的我们可以调用System.Attribute类型的GetCustomAttribute函数来获得指定编程单元附加的指定类型的特性对象。从编程角度看,特性也是一种对象类型,它们都是从System.Attribute上面派生的。.NET类库中已经定义了大量的特性类型,我们也可以定义自己的特性。使用特性也很简单,也就是在编程单元前面使用方括号包含特性的定义,比如对于WinForm程序其入口函数具有以下类似的定义。在这里,函数定义前头的“[Ssystem.STAThread]”就表示这个函数附加了一个类型名为“System.STAThreadAttribute”的特性,这里存在一个C#的语法,在附加特性时可以将类型名称后面的“Attribute”后缀去掉,当然也可以写全名。一个编程单元可以附加多个特性。/// <summary>
/// 应用程序的主入口点。
/// </summary>
[System.STAThread]
static void Main()
{
Application.Run(new frmTestORM());
}
使用特性,我们可以在对象属性上附加数据库字段映射信息,使用反射,我们可以动态的读取和设置对象的属性值。这样特性和反射可以成为我们实行ORM的技术基础。关于反射和特性的详细信息可以参考MSND中的相关文档。