反射的高级运用:通过一个实体类,以及查询到数据库的DataReader,进行绑定。
我们传统的绑定数据的做法是,写一个实体类,然后在DAO里面,各种 dr[“name”] 还要各种的判断,如果实体类修改了,就要修改DAO里面的代码,现在通过反射,可以更灵活。
需要准备的东东
一:实体类一个,只要的作用就是拿来反射
二:DataReader一个,表示从数据库查询出来的包含结果数据集(可以是查询单个结果,只包含一个结果的数据集,也可以是多个结果)
代码准备
1:先根据实体类或者是类别,获得一个类型的所有的共同属性,放到数组里面
2:再根据 DataReader,和 实体类的一组 共同属性的数组,循环公共属性,判断公共属性在DataReader里面的索引号(例如 name 这个属性,在 dr 里面可能是 0 号位,也可能是 2号位 )
3:最后,再根据DataReader,类型type,类型type的公共属性,以及索引号来创建这个类的实例对象,并为对象赋值。
1:根据类的类型,获得类型里面的属性
Type objType = typeof(Feedback);//获得一个对象的 类型 gv_FeedBack.DataSource = GetPropertis(objType); gv_FeedBack.DataBind();
/// <summary>根据 一个指定的type类型,返回所有的公共属性,放到数组里面 /// /// </summary> /// <param name="objType"></param> /// <returns></returns> private static ArrayList GetPropertis(Type objType) { //先看看缓存里面有没有 ArrayList objPropertis = (ArrayList)MyCache.Instance().Get(objType.FullName); if (objPropertis==null) { objPropertis=new ArrayList(); //缓存里面没有的话,就根据type类型,循环读取出 foreach (PropertyInfo objProperty in objType.GetProperties()) { objPropertis.Add(objProperty); } MyCache.Instance().Add(objType.FullName, objPropertis); } return objPropertis; }
2:再根据 DataReader,和 实体类的一组 共同属性的数组,循环公共属性,判断公共属性在DataReader里面的索引号(例如 name 这个属性,在 dr 里面可能是 0 号位,也可能是 2号位 )
IDataReader dr = new FeedbackDAO().GetModelList(); int[] arrOrdinals = GetOrdinals(GetPropertis(objType), dr); gv_FeedBack.DataSource = arrOrdinals; gv_FeedBack.DataBind(); } //获取实体类的属性在Dr里面对应的列的索引号,如果存在,返回索引号,如果不存在,那么那个实体类字段的索引号为-1 private static int[] GetOrdinals(ArrayList objProperties, IDataReader dr) { PropertyInfo objPropertyInfo = null; int[] arrOrdinals = new int[objProperties.Count]; if (dr != null) { for (int i = 0; i < objProperties.Count; i++) { arrOrdinals[i] = -1; objPropertyInfo = (PropertyInfo)objProperties[i]; try { //通过实体类的属性的名称, 来判断属性在在dr里面时候存在, 如果属性存在,那么返回这个属性在dr里面的索引值 //如果不存在,这表示返回的dr里面,不存在实体类对应的属性 //这里用try是因为,假如实体类的属性名objPropertyInfo.Name是 Address,但是实际上dr返回的是DiZhi, //或者压根就没有Address,那么这里就会报错,说dr里面找不到一个叫做 Address的列,问你是不是列名错误, //我们用try就是表示尝试,如果报错,这里赋值就不成功,那么arrOrdinals[i]就是等于上面的 -1 //如果匹配成功,就表示我们在dr里面,找到了实体类的属性名称一样的列,那么我们就获取这个列对应的序列号,是在0号列还是2号列 arrOrdinals[i] = dr.GetOrdinal(objPropertyInfo.Name); } catch (Exception ex) { string a = ex.Message; } } } return arrOrdinals; }
例如,这里的实体类是
,而我返回的dr里面的数据的列是下面这个样子,很显然,我dr的第一列,是一个中文的”哈哈”,完全和实体类对应不上
那么最后返回的结果是
3:最后,再根据DataReader,类型type,类型type的公共属性,以及索引号来创建这个类的实例对象,并为对象赋值。