第13章使用反射和特性构造ORM框架13.1ORM背景13.2基础知识13.3软件设计13.4软件开发13.5部署ORM框架13.1ORM背景ORM是英文Object/RelationMapping的简写,翻译成中文就是对象-关系数据库映射。是一种为了解决面向对象编程思想和关系数据库技术存在的不匹配的问题而提出的技术思想。在数据库界,主流的数据库都是关系型数据库,其采用的关系型数据结构模型,无论从数学理论上还是实践中都相当的成熟,因此得到非常广泛的应用。在业界,面向对象的编程思想及其派生思想占据主流。13.2基础知识13.2.1反射与特性1.反射反射是.NET框架提供的一种高级编程接口,是一种获取元数据类型的技术。在C#编程语言中,程序集在加载时提供一个描述自身的元数据结构,通过这些描述的元数据结构,应用反射技术获取程序集中包含的类型、成员、属性、接口、方法等信息。使用反射技术能够在运行时根据指定类的名称创建类的实例。13.2.1反射与特性【例13.1】编写一个控制台程序说明如何在程序中使用System.Type查询类型信息。实现步骤如下:(1)创建一个控制台应用程序,命名为“ExTypeInfo”。(2)在Program.cs代码文件中创建一个类“Employee”,代码如下:internalclassEmployee{privatestringm_name;publicstringName{get{returnm_name;}set{m_name=value;}}}13.2.1反射与特性(3)在Main方法中添加如下代码,用来获取Employee类实例的类型信息并输出。代码如下:Employeeemloyee=newEmployee();TypeobjType=emloyee.GetType();Console.Write(类型名称:);Console.WriteLine(objType.Name);Console.WriteLine(类型全名:);Console.WriteLine(objType.FullName);Console.WriteLine(所在命名空间:);Console.WriteLine(objType.Namespace);Console.WriteLine(所在模块:);Console.WriteLine(objType.Module.Name);Console.WriteLine(所在程序集:);Console.WriteLine(objType.Assembly.FullName);Console.WriteLine(基类名称:);Console.WriteLine(objType.BaseType.FullName);Console.WriteLine(是否是类:);Console.WriteLine(objType.IsClass?是:否);Console.WriteLine(是否是公共类:);Console.WriteLine(objType.IsPublic?是:否);13.2.1反射与特性(4)运行程序,运行结果如图13.1所示。13.2.1反射与特性2.特性特性也是.NET框架提供的一种高级编程手段。它是附加在类型,字段,属性,函数等编程单元上面的额外信息,就相当于Access数据库中的表和字段的说明文本。特性的使用方法如下段代码所示:///summary///应用程序的主入口点。////summary[System.STAThread]staticvoidMain(){Application.Run(newfrmTestORM());}13.2.2Object类因为.NETFramework中的所有类均从Object派生,所以Object类中定义的每个方法可用于系统中的所有对象。Object类的常用方法如表13.1所示。名称访问类型描述EqualsPublic确定两个Object实例是否相等。GetHashCodePublic用作特定类型的哈希函数。GetHashCode适合在哈希算法和数据结构(如哈希表)中使用。GetTypePublic获取当前实例的Type。ReferenceEqualsPublic确定指定的Object实例是否是相同的实例。ToStringPublic返回表示当前Object的String。Finalizeprotected允许Object在“垃圾回收”回收Object之前尝试释放资源并执行其他清理操作。MemberwiseCloneprotected创建当前Object的浅表副本。13.2.3Hashtable类Hashtable类的常用方法和属性如表13.2和表13.3所示。名称描述Add将带有指定键和值的元素添加到Hashtable中。Clear从Hashtable中移除所有元素。Clone创建Hashtable的浅表副本。Contains确定Hashtable是否包含特定键。ContainsKey确定Hashtable是否包含特定键。ContainsValue确定Hashtable是否包含特定值。CopyTo将Hashtable元素复制到一维Array实例中的指定索引位置。GetEnumerator返回循环访问Hashtable的IDictionaryEnumerator。GetObjectData实现ISerializable接口,并返回序列化Hashtable所需的数据。OnDeserialization实现ISerializable接口,并在完成反序列化之后引发反序列化事件。Remove从Hashtable中移除带有指定键的元素。13.2.3Hashtable类名称描述Count获取包含在Hashtable中的键/值对的数目。IsFixedSize获取一个值,该值指示Hashtable是否具有固定大小。IsReadOnly获取一个值,该值指示Hashtable是否为只读。IsSynchronized获取一个值,该值指示是否同步对Hashtable的访问(线程安全)。Item获取或设置与指定的键相关联的值。Keys获取包含Hashtable中的键的ICollection。SyncRoot获取可用于同步Hashtable访问的对象。Values获取包含Hashtable中的值的ICollection。表13.3Hashtable类的常用属性13.2.4TypeConverter类TypeConverter类的常用方法如表13.4所示。名称描述CanConvertFrom返回该转换器是否可以将一种类型的对象转换为此转换器的类型。CanConvertTo返回此转换器是否可将该对象转换为指定的类型。ConvertFrom将给定值转换为此转换器的类型。ConvertFromInvariantString使用不变区域性将该值转换为此转换器的类型。ConvertFromString将指定文本转换为对象。ConvertTo将给定值对象转换为指定的类型。ConvertToInvariantString将指定值转换为区域性不变的字符串表示形式。ConvertToString将指定值转换为字符串表示形式。CreateInstance在给定Object的一组属性值的情况下重新创建该对象。GetCreateInstanceSupported返回更改此对象的值是否要求调用CreateInstance方法来创建新值。GetProperties返回由值参数指定的数组类型的属性(Property)集合。GetPropertiesSupported返回此对象是否支持属性。GetStandardValues返回此类型转换器设计用于的数据类型的标准值集合。GetStandardValuesExclusive返回从GetStandardValues返回的标准值的集合是否为独占列表。GetStandardValuesSupported返回此对象是否支持可以从列表中选取的标准值集。IsValid返回给定值对象对于此类型是否有效。13.2.5TypeDescriptor类TypeDescriptor类在System.ComponentModel命名空间中,提供有关组件特性(Attribute)的信息,如组件的特性(Attribute)、属性(Property)和事件。表13.5显示这些服务。名称描述IExtenderProvider启用其他类(如ToolTip),以便为组件提供额外的属性(Property)。ITypeDescriptorFilterService启用其他对象,以便修改由组件公开的标准元数据。ICustomTypeDescriptor启用一个类,以便完全且动态地指定其自身的元数据,进而替换TypeDescriptor的标准检查机制。TypeDescriptor类的常用方法和属性如表13.6和表13.7所示。13.2.6IFormattable接口【例13.2】编写一个控制台程序,定义一个实现IFormattable接口的Temperature类。该类支持四个格式说明符:G和C,指示温度以摄氏度显示;F,指示温度以华氏度显示;K,指示温度以开氏度显示。实现步骤如下:(1)创建一个控制台应用程序,命名为“TemperatureFormat”。(2)在Program.cs代码文件中添加命名空间“usingSystem.Globalization;”,并创建一个继承于IFormattable接口的类“Temperature”,其代码为。13.2.6IFormattable接口(3)在Main方法中添加如下代码,以不同的方法显示。代码如下:Temperaturetemp1=newTemperature(0);Console.WriteLine({0:C}(摄氏)={0:K}(开氏)={0:F}(华氏)\n,temp1);temp1=newTemperature(-40);Console.WriteLine(String.Format(CultureInfo.CurrentCulture,{0:C}(华氏)={0:K}(开氏)={0:F}(华氏),temp1));Console.WriteLine(String.Format(newCultureInfo(fr-FR),{0:C}(华氏)={0:K}(开氏)={0:F}(华氏)\n,temp1));temp1=newTemperature(32);Console.WriteLine({0}(华氏)={1}(开氏)={2}(华氏)\n,temp1.ToString(C),temp1.ToString(K),temp1.ToString(F));temp1=newTemperature(100);NumberFormatInfocurrent=NumberFormatInfo.CurrentInfo;CultureInfonl=newCultureInfo(nl-NL);Console.WriteLine({0}(华氏)={1}(开氏)={2}(华氏),temp1.ToString(C,current),temp1.ToString(K,current),temp1.ToString(F,current));Console.WriteLine({0}(华氏)={1}(开氏)={2}(华氏),temp1.ToString(C,nl),temp1.ToString(K,nl),temp1.ToString(F,nl));13.2.6IFormattable接口(4)运行程序,运行结果如图13.2所示。13.2.7PropertyInfo类ProperyInfo类的常用方法和属性如表13.8和表13.9所示。名称描述GetAccessors返回此属性上的get和set访问器数组。GetConstantValue由编译器返回与属性(Property)关联的文本值。GetCustomAttributes在派生类中被重写时,返回应