本人大二菜鸟一只,今天在上课期间有个同学看着C#反射的内容说反射没什么用,一时之间也想不到什么更好的例子,就写了个根据泛型类型和游标反射创建List集合的Demo.
首先创建一个用于封装对应数据的entity,代码如下.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Test { public class EUserInfo { public int UserId { get; set; } public string UserCode { get; set; } public string UserName { get; set; } public string UserPwd { get; set; } public string Gender { get; set; } public override string ToString() { return "UserId:"+UserId+"|UserCode:"+UserCode+"|UserName:"+UserName+"|UserPwd:"+UserPwd+"|Gender:"+Gender; } } }
这里我重写了ToString方法,以便待会儿更直观的看到效果.
接下来创建EUserInfo实体类对应的table,sql如下:
use master go if exists (select * from sys.databases where name='reflectDemoDB') drop database reflectDemoDB create database reflectDemoDB go use reflectDemoDB go create table UserInfo( UserId int primary key identity, UserCode ) not null, UserName ) not null, UserPwd ) not null, Gender ) check(Gender in ('男','女')) ) go ','男') ','男') ','男')
为了可以方便操作ado对象我这里写了一个工具类DBHelper,代码如下:
using System; using System.Collections.Generic; using System.Web; using System.Data.SqlClient; using System.Data; using System.Configuration; namespace Test { /// <summary> ///DBHelper:数据库访问操作类 /// </summary> public class DBHelper { /// <summary> /// 更新操作:增,删,改 共用 /// </summary> /// <param name="sql"></param> /// <returns>bool</returns> public static bool UpdateOpera(string sql,params SqlParameter[] sps) { SqlCommand cmd = new SqlCommand(sql, Connection); //////////////////将配置参数加入到Command中 cmd.Parameters.AddRange(sps); ///////////////// ; } /// <summary> /// 单个查询操作:返回首行首列数据 /// </summary> /// <param name="sql">查询SQL语句</param> /// <returns>object</returns> public static object GetScalar(string sql, params SqlParameter[] sps) { SqlCommand cmd = new SqlCommand(sql, Connection); //////////////////将配置参数加入到Command中 cmd.Parameters.AddRange(sps); ///////////////// return cmd.ExecuteScalar(); } /// <summary> /// 多行查询操作:返回SqlDataReader /// </summary> /// <param name="sql">查询SQL语句</param> /// <returns>SqlDataReader</returns> public static SqlDataReader GetReader(string sql, params SqlParameter[] sps) { SqlCommand cmd = new SqlCommand(sql, Connection); //////////////////将配置参数加入到Command中 cmd.Parameters.AddRange(sps); ///////////////// return cmd.ExecuteReader(); } /// <summary> /// 多行查询操作:返回DataTable /// </summary> /// <param name="sql">查询SQL语句</param> /// <returns>DataTable</returns> public static DataTable GetDataTable(string sql, params SqlParameter[] sps) { DataTable dt = new DataTable(); SqlDataAdapter dad = new SqlDataAdapter(sql, Connection); //////////////////将配置参数加入到Command中 dad.SelectCommand.Parameters.AddRange(sps); ///////////////// dad.Fill(dt); return dt; } public static List<string> GetColumnsByTableName(string tableName) { List<string> columnList = new List<string>(); string sql = "select name from syscolumns where id=object_id(@tableName)"; SqlDataReader sdr = GetReader(sql, new SqlParameter("@tableName", tableName)); while (sdr.Read()) { columnList.Add(sdr["name"].ToString()); } sdr.Close(); return columnList; } private static SqlConnection _connection; /// <summary> /// Connection对象 /// </summary> public static SqlConnection Connection { get { string connectionString = "Data Source=.;Initial Catalog=reflectDemoDB;Integrated Security=True"; if (_connection == null) { _connection = new SqlConnection(connectionString); _connection.Open(); } else if (_connection.State == ConnectionState.Closed) { _connection.Open(); } else if (_connection.State == ConnectionState.Broken || _connection.State == ConnectionState.Open) { _connection.Close(); _connection.Open(); } return _connection; } } } }
接下来就可以进入主题了,我这里是用一个BaseDao做例子,代码如下:
using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace Test { public class BaseDao<T> { /// <summary> /// 获取泛型对应的实体类类名当做表名 /// </summary> private static string TableName { get { return typeof(T).Name.Replace("E",""); } } /// <summary> /// 获取泛型对应实体类所有属性 /// </summary> private static PropertyInfo[] Properties { get { return typeof(T).GetProperties(); } } /// <summary> /// 通用查询所有方法 /// </summary> /// <returns></returns> public List<T> GetAll() { //根据获取的表名拼装出sql语句 string sql = "select * from " + TableName; SqlDataReader sdr = DBHelper.GetReader(sql); return CreateInstanceListOfSqlDataReader<T>(sdr); } private static T CreateInstance<T>(SqlDataReader sdr) { //或许泛型类所有属性 //根据泛型T创建它的实例 T t = (T)Activator.CreateInstance(typeof(T)); //遍历该类所有属性 foreach (PropertyInfo pro in Properties) { //判断属性类型 如果是对应类型就强转进行赋值 if (pro.PropertyType.Equals(typeof(DateTime))) try { pro.SetValue(t, Convert.ToDateTime(sdr[pro.Name]));//利用游标根据属性名获取对应列值给属性赋值 } catch (Exception) { throw new Exception("转换DateTime类型失败,[" + pro.Name + "]字段[value=" + sdr[pro.Name].ToString() + "]格式不正确"); } else if (pro.PropertyType.Equals(typeof(int))) try { pro.SetValue(t, Convert.ToInt32(sdr[pro.Name])); } catch (Exception) { throw new Exception("转换int类型失败,[" + pro.Name + "]字段[value=" + sdr[pro.Name].ToString() + "]格式不正确"); } else if (pro.PropertyType.Equals(typeof(double))) try { pro.SetValue(t, Convert.ToDouble(sdr[pro.Name])); } catch (Exception) { throw new Exception("转换Double类型失败,[" + pro.Name + "]字段[value=" + sdr[pro.Name].ToString() + "]格式不正确"); } else pro.SetValue(t, sdr[pro.Name]); } return t; } /// <summary> /// 根据游标sdr创建一个所传类型对象集合并返回 /// </summary> /// <typeparam name="T">泛型类型</typeparam> /// <param name="sdr">游标</param> /// <returns></returns> private List<T> CreateInstanceListOfSqlDataReader<T>(SqlDataReader sdr) { List<T> tList = new List<T>(); while (sdr.Read()) { T t = CreateInstance<T>(sdr); tList.Add(t); } return tList; } } }
BaseDao写好以后我们就可以看看效果了,接下来我们创建一个UserInfoDao,来继承BaseDao,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Test { public class UserInfoDao:BaseDao<EUserInfo>{} }
然后我们就可以开始测试了,下面是测试代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Test { class Program { static void Main(string[] args) { UserInfoDao userInfoDao = new UserInfoDao(); List<EUserInfo> userInfoList = userInfoDao.GetAll(); foreach (EUserInfo userInfo in userInfoList) { Console.WriteLine(userInfo); } Console.ReadKey(); } } }
这里我们可以直接调用BaseDao的GetAll方法,sql会自动在BaseDao中帮我们拼装好,得到的结果如下:
这里我们可以看见的效果是BaseDao帮我们把数据库中表的数据封装到了对象中.不需要我们手动的来进行实例化赋值,希望这个Demo能对初学反射的有点启发,有什么不足之处大家多多指教.