C# ORM中反射与泛型的交叉应用

来源:互联网 发布:数据的预处理包括什么 编辑:程序博客网 时间:2024/05/29 15:01

好久没有写文章了,终于找到工作,抽空写一下冒个泡。

问题

最近遇到一个这样 ORM 的问题,一个返回类型为 List 泛型方法中,需要做到根据条件访问数据库,并且把得到的结果存入 List 中返回。

由于只是以前学过一段时间的 C#,而且反射一直个人认为是各中难点,加上泛型,这篇文章纯属个人纪录,如有错误,望各位大佬指正。

分析

根据条件访问数据库 ==> 遍历获取到的 reader 对象 ==> 创建泛型实例以及泛型 List,并且对实例赋值存入 List ==> 遍历完成,返回当前的 List

从上面的几个步骤中我们可以发现,难点就是在于这个泛型实例的创建以及它的属性赋值。我们可以通过 Activator 的CreateInstance(type) 方法创建,然后通过 type.setValue(object,value,index) 来设置对应的属性值,至于如何匹配这些属性值,我们就通过 ORM 中来映射获取到对应的特性值与数据库字段的匹配。这样问题就解决了。

解决方法

这里分为几个步骤,

  1. 获取到数据库的返回(ps:这个比较简单我就不多说了,具体可以直接百度,狗狗都有很多)
  2. 获取到对应的泛型的类型
    这里是通过 typeof() 方法
  3. 通过获取到的类型由 Activator 类的 CreateInstance(type) 方法创建 object 实例
  4. 通过 type 获取到此实例的属性列表
  5. 遍历属性列表,并与 数据库 中的属性对比匹配,得到匹配成功的特性信息。
  6. 判断特性信息,为空就跳过,不为空就通过 setValue(object,value,index) 方法设置属性的对应值,并添加到 List 中。

代码

private const string SELECT = "SELECT * FROM dbo.Alvin ";public static List<TEntity> Query<TEntity>(string condition)        {            using (var conn = SqlHelper.Instance.GetConnection())            {                var reader = SqlHelper                   .Instance                   .ExecuteQuery(conn,                   SELECT + condition,                   new List<SqlParameter> {                   });                List<TEntity> list = new List<TEntity>();                //获取到泛型的类型                Type type = typeof(TEntity);                //通过反射由类型创建对应object实例                object o = Activator.CreateInstance(type);                //通过类型获取到有的属性                var infos = type.GetProperties();                while (reader.Read())                {                    //Console.WriteLine("infos 数量:{0}",infos.Length);                    foreach (var info in infos)                    {                        //Console.WriteLine("info 不为空");                        //获取到属性对应的特性信息(这里就做了匹配)                        object[] ob = info.GetCustomAttributes(typeof(FieldAttribute), false);                        if (ob != null)                        {                            //通过反射设置对应的属性值,o代表与o绑定                            info.SetValue(o, reader[((FieldAttribute)ob[0]).Fields], null);                            //Console.WriteLine("结果是:{0}", reader[((FieldAttribute)ob[0]).Fields]);                        }                                }                    //添加到list中                    list.Add((TEntity)o);                }                return list;            }        }

这里 ORM 就不贴上了,这里 Record 类是完全匹配数据库里表段的,但是 RecordLess 是不完全匹配,暂时只测试到这么多,还有一类就是啥都没有匹配的还没测试过,

结果

RecordLess

RecordLess

Record

Record

原创粉丝点击