在C#中通过反射机制将查询到的DataTable或DataReader转换成相对应的对象类型。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 ///2 /// 反射操作工具类 3 /// 4 public class ReflectionUtil 5 { 6 #region 根据反射机制将dataTable中指定行的数据赋给obj对象 7 8 ///9 /// 根据反射机制将dataTable中指定行的数据赋给obj对象 10 /// 11 /// obj对象 12 /// dataTable 13 /// 指定行 14 public static void ConvertDataRowToModel(object obj, DataTable dataTable, int rowIndex) 15 { 16 //指定行不存在 17 if (dataTable.Rows.Count < (rowIndex + 1)) 18 throw new Exception("指定行不存在!"); 19 20 //DataTable列为空! 21 if (dataTable.Columns.Count < 1) 22 throw new Exception("DataTable列为空!"); 23 24 Type type = obj.GetType(); 25 PropertyInfo[] pInfos = type.GetProperties(); 26 27 try 28 { 29 for (int i = 0; i < dataTable.Columns.Count; i++) 30 { 31 for (int j = 0; j < pInfos.Length; j++) 32 { 33 //全部转换为小写的作用是防止数据库列名的大小写和属性的大小写不一致 34 if (dataTable.Columns[i].ColumnName.ToLower() == pInfos[j].Name.ToLower()) 35 { 36 PropertyInfo pInfo = type.GetProperty(pInfos[j].Name); //obj某一属性对象 37 object colValue = dataTable.Rows[rowIndex][i]; //DataTable 列值 38 SetObjectValue(obj, colValue, pInfo, pInfos, j); 39 break; 40 } 41 } 42 } 43 } 44 catch (Exception ex) 45 { 46 //LogTxt.LogException(ex.Message + "\r\n" + ex.Source + "\r\n" + ex.TargetSite + "\r\n" + ex.StackTrace + "\r\n"); 47 throw ex; 48 } 49 } 50 51 #endregion 52 53 #region 将值赋给object属性 54 55 public static void SetObjectValue(object obj, object colValue, PropertyInfo pInfo, PropertyInfo[] pInfos, int j) 56 { 57 if (!ObjectIsNull(colValue)) 58 { 59 if (pInfos[j].PropertyType.FullName == "System.String") 60 { 61 pInfo.SetValue(obj, Convert.ToString(colValue), null); 62 } 63 else if (pInfos[j].PropertyType.FullName == "System.Int32") 64 { 65 pInfo.SetValue(obj, Convert.ToInt32(colValue), null); 66 } 67 else if (pInfos[j].PropertyType.FullName == "System.Int64") 68 { 69 pInfo.SetValue(obj, Convert.ToInt64(colValue), null); 70 } 71 else if (pInfos[j].PropertyType.FullName == "System.Single") 72 { 73 pInfo.SetValue(obj, Convert.ToSingle(colValue), null); 74 } 75 else if (pInfos[j].PropertyType.FullName == "System.Double") 76 { 77 pInfo.SetValue(obj, Convert.ToDouble(colValue), null); 78 } 79 else if (pInfos[j].PropertyType.FullName == "System.Decimal") 80 { 81 pInfo.SetValue(obj, Convert.ToDecimal(colValue), null); 82 } 83 else if (pInfos[j].PropertyType.FullName == "System.Char") 84 { 85 pInfo.SetValue(obj, Convert.ToChar(colValue), null); 86 } 87 else if (pInfos[j].PropertyType.FullName == "System.Boolean") 88 { 89 pInfo.SetValue(obj, Convert.ToBoolean(colValue), null); 90 } 91 else if (pInfos[j].PropertyType.FullName == "System.DateTime") 92 { 93 pInfo.SetValue(obj, Convert.ToDateTime(colValue), null); 94 } 95 //可空类型 96 else if (pInfos[j].PropertyType.FullName == "System.Nullable`1[[System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]") 97 { 98 pInfo.SetValue(obj, Convert.ToDateTime(colValue), null); 99 }100 else if (pInfos[j].PropertyType.FullName == "System.Nullable`1[[System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")101 {102 pInfo.SetValue(obj, Convert.ToDateTime(colValue), null);103 }104 else if (pInfos[j].PropertyType.FullName == "System.Nullable`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")105 {106 pInfo.SetValue(obj, Convert.ToInt32(colValue), null);107 }108 else if (pInfos[j].PropertyType.FullName == "System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")109 {110 pInfo.SetValue(obj, Convert.ToInt32(colValue), null);111 }112 else if (pInfos[j].PropertyType.FullName == "System.Nullable`1[[System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")113 {114 pInfo.SetValue(obj, Convert.ToInt64(colValue), null);115 }116 else if (pInfos[j].PropertyType.FullName == "System.Nullable`1[[System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")117 {118 pInfo.SetValue(obj, Convert.ToInt64(colValue), null);119 }120 else if (pInfos[j].PropertyType.FullName == "System.Nullable`1[[System.Decimal, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")121 {122 pInfo.SetValue(obj, Convert.ToDecimal(colValue), null);123 }124 else if (pInfos[j].PropertyType.FullName == "System.Nullable`1[[System.Decimal, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")125 {126 pInfo.SetValue(obj, Convert.ToDecimal(colValue), null);127 }128 else if (pInfos[j].PropertyType.FullName == "System.Nullable`1[[System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")129 {130 pInfo.SetValue(obj, Convert.ToBoolean(colValue), null);131 }132 else if (pInfos[j].PropertyType.FullName == "System.Nullable`1[[System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]")133 {134 pInfo.SetValue(obj, Convert.ToBoolean(colValue), null);135 }136 else137 {138 throw new Exception("属性包含不支持的数据类型!");139 }140 }141 else142 {143 pInfo.SetValue(obj, null, null);144 }145 }146 147 #endregion148 149 #region 根据反射机制从obj对象取值并用该值添加datatable行150 151 ///152 /// 根据反射机制从obj对象取值并用该值添加datatable行153 /// 154 /// obj对象155 /// dataTable156 /// 指定行157 public static void ConvertModelToNewDataRow(object obj, DataTable dataTable, int rowIndex)158 {159 //DataTable列为空!160 if (dataTable.Columns.Count < 1)161 {162 throw new Exception("DataTable列为空!");163 }164 165 DataRow dr = dataTable.NewRow();166 Type type = obj.GetType();167 PropertyInfo[] pInfos = type.GetProperties();168 169 try170 {171 for (int i = 0; i < dataTable.Columns.Count; i++)172 {173 for (int j = 0; j < pInfos.Length; j++)174 {175 //全部转换为小写的作用是防止数据库列名的大小写和属性的大小写不一致176 if (dataTable.Columns[i].ColumnName.ToLower() == pInfos[j].Name.ToLower())177 {178 PropertyInfo pInfo = type.GetProperty(pInfos[j].Name);179 180 object beanValue = pInfo.GetValue(obj, null);181 182 //将bean中属性值赋给datarow183 if (!ObjectIsNull(beanValue))184 {185 dr[i] = beanValue;186 }187 else188 {189 dr[i] = DBNull.Value;190 }191 break;192 }193 }194 }195 196 dataTable.Rows.InsertAt(dr, rowIndex);197 dataTable.AcceptChanges();198 }199 catch (Exception ex)200 {201 //LogTxt.LogException(ex.Message + "\r\n" + ex.Source + "\r\n" + ex.TargetSite + "\r\n" + ex.StackTrace + "\r\n");202 throw ex;203 }204 }205 206 #endregion207 208 #region 根据反射机制从obj对象取值并赋给datatable的指定行209 210 ///211 /// 根据反射机制从obj对象取值并赋给datatable的指定行212 /// 213 /// obj对象214 /// dataTable215 /// 指定行216 public static void ConvertModelToSpecDataRow(object obj, DataTable dataTable, int rowIndex)217 {218 //指定行不存在219 if (dataTable.Rows.Count < (rowIndex + 1))220 {221 throw new Exception("指定行不存在!");222 }223 224 //DataTable列为空!225 if (dataTable.Columns.Count < 1)226 {227 throw new Exception("DataTable列为空!");228 }229 230 Type type = obj.GetType();231 PropertyInfo[] pInfos = type.GetProperties();232 233 try234 {235 for (int i = 0; i < dataTable.Columns.Count; i++)236 {237 for (int j = 0; j < pInfos.Length; j++)238 {239 //全部转换为小写的作用是防止数据库列名的大小写和属性的大小写不一致240 241 if (dataTable.Columns[i].ColumnName.ToLower() == pInfos[j].Name.ToLower())242 {243 PropertyInfo pInfo = type.GetProperty(pInfos[j].Name);244 object beanValue = pInfo.GetValue(obj, null);245 246 //将bean中属性值赋给datarow247 if (!ObjectIsNull(beanValue))248 {249 dataTable.Rows[rowIndex][i] = beanValue;250 }251 else252 {253 dataTable.Rows[rowIndex][i] = DBNull.Value;254 }255 break;256 }257 }258 }259 dataTable.AcceptChanges();260 }261 catch (Exception ex)262 {263 //LogTxt.LogException(ex.Message + "\r\n" + ex.Source + "\r\n" + ex.TargetSite + "\r\n" + ex.StackTrace + "\r\n");264 throw ex;265 }266 }267 268 #endregion269 270 #region 根据对象名返回类实例271 272 ///273 /// 根据对象名返回类实例274 /// 275 /// 对象名称276 ///对象实例(可强制转换为对象实例) 277 public static object GetObjectByObjectName(string parObjectName)278 {279 Type t = Type.GetType(parObjectName); //找到对象280 return System.Activator.CreateInstance(t); //实例化对象281 }282 283 #endregion284 285 #region 判断对象是否为空286 287 ///288 /// 判断对象是否为空289 /// 290 /// 对象291 ///292 static public bool ObjectIsNull(Object obj)293 {294 //如果对象引用为null 或者 对象值为null 或者对象值为空295 if (obj == null || obj == DBNull.Value || obj.ToString().Equals("") || obj.ToString() == "")296 {297 return true;298 }299 return false;300 }301 302 #endregion303 304 #region 根据反射机制将DataTable转换为实体集合305 306 /// 307 /// 根据反射机制将DataTable转换为实体集合308 /// 309 ///实体类型 310 /// DataTable311 ///实体集合 312 public static ListConvertDataTableToModelList (DataTable dt)313 {314 if (dt == null)315 {316 return null;317 }318 List result = new List ();319 for (int i = 0; i < dt.Rows.Count; i++)320 {321 T t = Activator.CreateInstance ();322 ConvertDataRowToModel(t, dt, i);323 result.Add(t);324 }325 return result;326 }327 328 #endregion329 330 #region 根据反射机制将DataReader转换为实体集合331 332 /// 333 /// 根据反射机制将DataReader转换为实体集合334 /// 335 ///实体类型 336 /// DataReader337 ///实体 338 public static T ConvertDataReaderToModel(MySqlDataReader dr)339 {340 T obj = Activator.CreateInstance ();341 if (dr == null)342 throw new Exception("制定对象不存在。");343 344 if (!dr.Read())345 throw new Exception("无法读取数据。");346 347 Type type = obj.GetType();348 PropertyInfo[] pInfos = type.GetProperties();349 for (int i = 0; i < dr.FieldCount; i++)350 {351 for (int j = 0; j < pInfos.Length; j++)352 {353 if (dr.GetName(i).ToLower() == pInfos[j].Name.ToLower())354 {355 PropertyInfo pInfo = type.GetProperty(pInfos[j].Name); //obj某一属性对象 356 object colValue = dr[i]; //DataTable 列值357 SetObjectValue(obj, colValue, pInfo, pInfos, j);358 break;359 }360 }361 }362 //关闭363 if (!dr.IsClosed)364 {365 dr.Close();366 }367 return (T)obj;368 }369 370 #endregion371 372 /// 373 /// 通用(调用对象方法前先new一遍对象,故对象的状态无法保留;无用有无参构造函数,并调用无参方法),374 /// 375 ///376 /// 377 public static void InvokeMethod (string methodName, object[] param = null) where T : new()378 {379 T instance = new T();380 MethodInfo method = typeof(T).GetMethod(methodName, new Type[] { });381 method.Invoke(instance, param);382 }383 384 /// 385 /// 调用一个具体实例对象的方法,会保留对象状态386 /// 387 /// 388 /// 389 public static void InvokeMethod(object o, string methodName, object[] param = null)390 {391 o.GetType().GetMethod(methodName, new Type[] { }).Invoke(o, param);392 }393 }
调用方式
一、将查询到的DataTable转换成对象集合
1 ///2 /// 获取列表 3 /// 4 ///数据类型 5 /// 数据库连接字符串 6 /// SQL语句 7 ///数据集合 8 public static ListGetDataListBySQL (string _connectionString, string _sql) 9 {10 try11 {12 //读取数据库13 DataTable dt = MySqlHelper.ExecuteDataset(_connectionString, _sql).Tables[0];14 //通过反射获取实体集合15 return ReflectionUtil.ConvertDataTableToModelList (dt);16 }17 catch (Exception _ex)18 {19 //定义异常处理20 return default(List );21 }22 }
二、将查询到的DataReader转换成对象(以MySQL为例)
1 ///2 /// 获取对象 3 /// 4 ///数据类型 5 /// 数据库连接字符串 6 /// SQL语句 7 ///数据对象 8 public static T GetObjBySQL(string _connectionString, string _sql) 9 {10 try11 {12 //读取数据库13 MySqlDataReader dr = MySqlHelper.ExecuteReader(_connectionString, _sql);14 //通过反射获取实体15 return ReflectionUtil.ConvertDataReaderToModel (dr);16 }17 catch (Exception _ex)18 {19 //定义异常处理20 return default(T);21 }22 }
三、调用实体的对象方法
1.调用一个具体实例对象的方法,会保留对象状态。
////// 打开窗体/// private void OpenDialog(){ Form form = new Form(); ReflectionUtil.InvokeMethod(form, "ShowDialog"); ReflectionUtil.InvokeMethod(form, "Dispose");}
2.通过类型调用对象的方法,调用时会先new 一个实例,对象的状态无法保留。
1 ///2 /// 打开窗体3 /// 4 private void OpenDialog()5 {6 ReflectionUtil.InvokeMethod