利用反射把查询到的Table、Reader转换成List、Model
菜鸟一枚,入园已有两年三个月,这还是第一次写博客,请各位大神斧正。
这是我写的一个工具类,通常我们从数据库查询到一个 DataReader 或者是 一个 Table , 想要转换成 一个 list 或者是 一个model 的话 , 一般情况下是使用foreach 循环reader或是table的rows,然后在循环内创建个对象,通过reader[“列名”]来赋值对象的属性。如果表的字段少的话,用这种方式还可以,速度也快一点。但是如果后续还会增加字段的话,那就非常麻烦了,要改很多地方。这工作量太大了,而且还很容易出错。所以这个时候使用反射来转换的话就非常便捷了。我们只管增加字段,改一下数据表对应的model,调用这个工具类的方法,传入相对应的参数就能得到想要的结果。
诶,文笔不好,直接上代码吧。
1 public class DynamicGeneric 2 { 3 /// <summary> 4 /// table转list 5 /// </summary> 6 /// <typeparam name="T">list类型</typeparam> 7 /// <param name="obj">model对象</param> 8 /// <param name="table">数据源table</param> 9 /// <returns>list</returns> 10 public static List<T> FillListByDataTable<T>(T obj, DataTable table) 11 { 12 13 Type type = obj.GetType(); 14 15 List<T> list = new List<T>(); 16 17 PropertyInfo[] properties = type.GetProperties();//model对象的属性集合 18 19 DataColumnCollection dcc = table.Columns;//列集合 20 21 foreach (DataRow row in table.Rows) 22 { 23 //复制一个model对象 24 MemoryStream stream = new MemoryStream(); 25 BinaryFormatter formatter = new BinaryFormatter(); 26 formatter.Serialize(stream, obj); 27 stream.Position = 0; 28 T newObj = (T)formatter.Deserialize(stream); 29 30 foreach (PropertyInfo pro in properties) 31 { 32 Type tp = pro.PropertyType; 33 34 if (dcc.Contains(pro.Name.ToString())) 35 { 36 if (!string.IsNullOrEmpty(row[pro.Name].ToString())) 37 { 38 //判断字段类型 39 if (tp.Name != "Nullable`1") 40 { 41 pro.SetValue(newObj, Convert.ChangeType(row[pro.Name], tp, null)); 42 } 43 if (tp.Name != "Nullable`1") 44 { 45 pro.SetValue(newObj, Convert.ChangeType(row[pro.Name], tp)); 46 } 47 else if (tp.FullName.IndexOf("System.DateTime") > 0) 48 { 49 pro.SetValue(newObj, Convert.ChangeType(row[pro.Name], typeof(DateTime), null)); 50 } 51 else if (tp.FullName.IndexOf("System.Int32") > 0) 52 { 53 pro.SetValue(newObj, Convert.ChangeType(row[pro.Name], typeof(Int32), null)); 54 } 55 else if (tp.FullName.IndexOf("System.Int64") > 0) 56 { 57 pro.SetValue(newObj, Convert.ChangeType(row[pro.Name], typeof(Int64), null)); 58 } 59 else if (tp.FullName.IndexOf("System.Decimal") > 0) 60 { 61 pro.SetValue(newObj, Convert.ChangeType(row[pro.Name], typeof(Decimal), null)); 62 } 63 else if (tp.FullName.IndexOf("System.Boolean") > 0) 64 { 65 pro.SetValue(newObj, Convert.ChangeType(row[pro.Name], typeof(Boolean), null)); 66 } 67 } 68 69 } 70 } 71 list.Add(newObj); 72 } 73 return list; 74 } 75 76 /// <summary> 77 /// reader转list 78 /// </summary> 79 /// <typeparam name="T">list类型</typeparam> 80 /// <param name="obj">model对象</param> 81 /// <param name="reader">数据源reader</param> 82 /// <returns>list </returns> 83 public static List<T> FillListByDataReader<T>(T obj ,IDataReader reader) 84 { 85 List<T> list = new List<T>(); 86 87 Type t = obj.GetType(); 88 89 PropertyInfo[] proList = t.GetProperties(); 90 91 while(reader.Read()) 92 { 93 MemoryStream stream = new MemoryStream(); 94 BinaryFormatter formatter = new BinaryFormatter(); 95 formatter.Serialize(stream, obj); 96 stream.Position = 0; 97 T newObj = (T)formatter.Deserialize(stream); 98 99 foreach (PropertyInfo pro in proList) 100 { 101 Type tp = pro.PropertyType; 102 103 DataFieldAttribute attr = pro.GetCustomAttributes().Count() > 0 ? pro.GetCustomAttributes().First() as DataFieldAttribute : null; 104 105 if (attr != null && attr.ColumnName == pro.Name) 106 { 107 if (ReaderExists(reader, pro.Name) && !string.IsNullOrEmpty(reader[pro.Name].ToString())) 108 { 109 if (tp.Name != "Nullable`1") 110 { 111 pro.SetValue(newObj, Convert.ChangeType(reader[pro.Name], tp)); 112 } 113 else if (tp.FullName.IndexOf("System.DateTime") > 0) 114 { 115 pro.SetValue(newObj, Convert.ChangeType(reader[pro.Name], typeof(DateTime), null)); 116 } 117 else if (tp.FullName.IndexOf("System.Int32") > 0) 118 { 119 pro.SetValue(newObj, Convert.ChangeType(reader[pro.Name], typeof(Int32), null)); 120 } 121 else if (tp.FullName.IndexOf("System.Int64") > 0) 122 { 123 pro.SetValue(newObj, Convert.ChangeType(reader[pro.Name], typeof(Int64), null)); 124 } 125 else if (tp.FullName.IndexOf("System.Decimal") > 0) 126 { 127 pro.SetValue(newObj, Convert.ChangeType(reader[pro.Name], typeof(Decimal), null)); 128 } 129 else if (tp.FullName.IndexOf("System.Boolean") > 0) 130 { 131 pro.SetValue(newObj, Convert.ChangeType(reader[pro.Name], typeof(Boolean), null)); 132 } 133 } 134 } 135 } 136 list.Add(newObj); 137 } 138 139 return list; 140 } 141 142 /// <summary> 143 /// reader转model对象 144 /// </summary> 145 /// <typeparam name="T">类型</typeparam> 146 /// <param name="obj">model对象</param> 147 /// <param name="reader">数据源reader</param> 148 /// <returns>model对象</returns> 149 public static T FillObjectByDataReader<T>(T obj, IDataReader reader) 150 { 151 Type t = obj.GetType(); 152 153 PropertyInfo[] proList = t.GetProperties(); 154 155 if (reader.Read()) 156 { 157 foreach (PropertyInfo pro in proList) 158 { 159 Type tp = pro.PropertyType; 160 161 DataFieldAttribute attr = pro.GetCustomAttributes().Count() > 0 ? pro.GetCustomAttributes().First() as DataFieldAttribute : null; 162 163 if (attr != null && attr.ColumnName == pro.Name) 164 { 165 if (ReaderExists(reader, pro.Name) && !string.IsNullOrEmpty(reader[pro.Name].ToString())) 166 { 167 if (tp.Name != "Nullable`1") 168 { 169 pro.SetValue(obj, Convert.ChangeType(reader[pro.Name], tp)); 170 } 171 else if (tp.FullName.IndexOf("System.DateTime") > 0) 172 { 173 pro.SetValue(obj, Convert.ChangeType(reader[pro.Name], typeof(DateTime), null)); 174 } 175 else if (tp.FullName.IndexOf("System.Int32") > 0) 176 { 177 pro.SetValue(obj, Convert.ChangeType(reader[pro.Name], typeof(Int32), null)); 178 } 179 else if (tp.FullName.IndexOf("System.Int64") > 0) 180 { 181 pro.SetValue(obj, Convert.ChangeType(reader[pro.Name], typeof(Int64), null)); 182 } 183 else if (tp.FullName.IndexOf("System.Decimal") > 0) 184 { 185 pro.SetValue(obj, Convert.ChangeType(reader[pro.Name], typeof(Decimal), null)); 186 } 187 else if (tp.FullName.IndexOf("System.Boolean") > 0) 188 { 189 pro.SetValue(obj, Convert.ChangeType(reader[pro.Name], typeof(Boolean), null)); 190 } 191 } 192 } 193 } 194 } 195 196 return obj; 197 } 198 199 /// <summary> 200 /// row转model对象 201 /// </summary> 202 /// <typeparam name="T">model类型</typeparam> 203 /// <param name="obj">model对象</param> 204 /// <param name="row">数据源row</param> 205 /// <returns>model对象</returns> 206 public static T FillObjectByDataTable<T>(T obj, DataRow row) 207 { 208 Type t = obj.GetType(); 209 210 PropertyInfo[] proList = t.GetProperties(); 211 212 foreach (PropertyInfo pro in proList) 213 { 214 Type tp = pro.PropertyType; 215 216 DataFieldAttribute attr = pro.GetCustomAttributes().Count() > 0 ? pro.GetCustomAttributes().First() as DataFieldAttribute : null; 217 218 if (attr != null && attr.ColumnName == pro.Name) 219 { 220 if (!string.IsNullOrEmpty(row[pro.Name].ToString())) 221 { 222 if (tp.Name != "Nullable`1") 223 { 224 pro.SetValue(obj, Convert.ChangeType(row[pro.Name], tp, null)); 225 } 226 if (tp.Name != "Nullable`1") 227 { 228 pro.SetValue(obj, Convert.ChangeType(row[pro.Name], tp)); 229 } 230 else if (tp.FullName.IndexOf("System.DateTime") > 0) 231 { 232 pro.SetValue(obj, Convert.ChangeType(row[pro.Name], typeof(DateTime), null)); 233 } 234 else if (tp.FullName.IndexOf("System.Int32") > 0) 235 { 236 pro.SetValue(obj, Convert.ChangeType(row[pro.Name], typeof(Int32), null)); 237 } 238 else if (tp.FullName.IndexOf("System.Int64") > 0) 239 { 240 pro.SetValue(obj, Convert.ChangeType(row[pro.Name], typeof(Int64), null)); 241 } 242 else if (tp.FullName.IndexOf("System.Decimal") > 0) 243 { 244 pro.SetValue(obj, Convert.ChangeType(row[pro.Name], typeof(Decimal), null)); 245 } 246 else if (tp.FullName.IndexOf("System.Boolean") > 0) 247 { 248 pro.SetValue(obj, Convert.ChangeType(row[pro.Name], typeof(Boolean), null)); 249 } 250 } 251 252 } 253 } 254 255 256 return obj; 257 } 258 259 /// <summary> 260 /// list转table 261 /// </summary> 262 /// <typeparam name="T">list类型</typeparam> 263 /// <param name="list">数据源list</param> 264 /// <param name="table">table</param> 265 /// <returns>table</returns> 266 public static DataTable FillDataTableByObject<T>(List<T> list , DataTable table) 267 { 268 if (list.Count > 0) 269 { 270 Type type = list[0].GetType(); 271 272 PropertyInfo[] properties = type.GetProperties(); 273 274 DataColumnCollection dcc = table.Columns; 275 276 foreach (var obj in list) 277 { 278 DataRow row = table.NewRow(); 279 foreach (PropertyInfo p in properties) 280 { 281 if (dcc.Contains(p.Name.ToString())) 282 { 283 row[p.Name] = p.GetValue(obj); 284 } 285 } 286 table.Rows.Add(row); 287 } 288 } 289 return table; 290 } 291 292 /// <summary> 293 /// 验证reader是否存在某列 294 /// </summary> 295 /// <param name="reader"></param> 296 /// <param name="columnName"></param> 297 /// <returns></returns> 298 private static bool ReaderExists(IDataReader reader,string columnName) 299 { 300 int count = reader.FieldCount; 301 for(int i = 0; i < count; i++) 302 { 303 if(reader.GetName(i).Equals(columnName)) 304 { 305 return true; 306 } 307 } 308 return false; 309 } 310 311 312 }