C#中,实体属性与数据库字段的进行反射赋值

在实际开发中,我们经常需要从数据库中读取数据并赋值给实体类的相应属性。在.Text的DataDTOProvider中存在大量这样的代码, 比如:

public Role[] GetRoles(IDataReader reader)
            {
            System.Collections.ArrayList al = new System.Collections.ArrayList();
            try
            {
            while (reader.Read())
            {
            Role role = new Role();
            if (reader["RoleID"] != DBNull.Value)
            {
            role.RoleID = (int)reader["RoleID"];
            }
            if (reader["Names"] != DBNull.Value)
            {
            role.Names = (string)reader["Names"];
            }
            if (reader["Description"] != DBNull.Value)
            {
            role.Description = (string)reader["Description"];
            }
            al.Add(role);
            }
            }
            finally
            {
            reader.Close();
            }
            return (Role[])al.ToArray(typeof(Role));
            }
            
 

对于上面的代码,我觉得有几点不优雅之处:
1、每次对Role的属性进行赋值时,都要检查reader的值是否为DBNull,出现了很多重复代码
2、每次对Role的属性进行赋值时,都要进行类型转换, 而Role属性的类型是已知的,是不是可以自动完成这样的转换?
3、每次对Role的属性进行赋值时,都要进行Role属性与数据库字段的对应。如果我们在设计数据库与实体类时,保证数据库字段与实体类属性采用同样的名称,那利用反射,我们可以通过代码自动进行属性与字段的对应。即使数据库字段与属性不同名,我们也可以通过更改查询语句,来做到这一点。
是不是可以对上面的代码进行改进,使代码变得更优雅?那优雅的代码应该是什么样的呢?如果我们用ReaderToObject(reader,role);取代它之前的对Role属性进行赋值的语句,是不是会使代码变得更优雅?ReaderToObject的作用就是自动完成将reader中的值写入到role中对应的属性中(前提是reader中的字段与role中对应的属性具有相同的名称)。现在我们的任务就是实现ReaderToObject, 有了强大的武器—Reflection,我们的任务就变得很轻松, 也不多说了,下面的代码是我的实现方法:

  

private void ReaderToObject(IDataReader reader, object targetObj)
            {
            for (int i = 0; i < reader.FieldCount; i++)
            {
            System.Reflection.PropertyInfo propertyInfo = targetObj.GetType().GetProperty(reader.GetName(i));
            if (propertyInfo != null)
            {
            if (reader.GetValue(i) != DBNull.Value)
            {
            if (propertyInfo.PropertyType.IsEnum)
            {
            propertyInfo.SetValue(targetObj, Enum.ToObject(propertyInfo.PropertyType, reader.GetValue(i)), null);
            }
            else
            {
            propertyInfo.SetValue(targetObj, reader.GetValue(i), null);
            }
            }
            }
            }
            }
            
 

ReaderToObject可以将reader中的数据读入到任何实体类中。数据库字段与实体类属性的映射原则是名称相同。当然,我们也可以通过配置文件来进行两者映射。
所有代码如下:

private void button2_Click(object sender, EventArgs e)
            {
            Role[] role;
            SqlConnection con = new SqlConnection("Data Source=SLY\\SQLEXPRESS;Initial Catalog=ManagerRoles;User ID=sa");
            SqlCommand cmd = new SqlCommand("select * from Roles",con);
            SqlDataReader dr;
            con.Open();
            dr = cmd.ExecuteReader();
            DataDAL dataDal = new DataDAL();
            role = dataDal.GetRoles(dr);
            con.Close();
            textBox2.Text = role[0].RoleID.ToString();
            textBox3.Text = role[0].Names.ToString();
            textBox4.Text = role[0].Description.ToString();
            }
            类:DataDAL
            public Role[] GetRoles(IDataReader reader)
            {
            System.Collections.ArrayList al = new System.Collections.ArrayList();
            try
            {
            while (reader.Read())
            {
            Role role = new Role();
            ReaderToObject(reader, role);
            al.Add(role);
            }
            }
            finally
            {
            reader.Close();
            }
            return (Role[])al.ToArray(typeof(Role));
            }
            private void ReaderToObject(IDataReader reader, object targetObj)
            {
            for (int i = 0; i < reader.FieldCount; i++)
            {
            System.Reflection.PropertyInfo propertyInfo = targetObj.GetType().GetProperty(reader.GetName(i));
            if (propertyInfo != null)
            {
            if (reader.GetValue(i) != DBNull.Value)
            {
            if (propertyInfo.PropertyType.IsEnum)
            {
            propertyInfo.SetValue(targetObj, Enum.ToObject(propertyInfo.PropertyType, reader.GetValue(i)), null);
            }
            else
            {
            propertyInfo.SetValue(targetObj, reader.GetValue(i), null);
            }
            }
            }
            }
            }
            实体类:Role
            int roleID;
            public int RoleID
            {
            get { return roleID; }
            set { roleID = value; }
            }
            string names;
            public string Names
            {
            get { return names; }
            set { names = value; }
            }
            string description;
            public string Description
            {
            get { return description; }
            set { description = value; }
            }
            
 

 

原创作者不晓得是谁,,,但是这个代码用着还是不太舒服,所以自己写了个。。。

如果有什么问题请多批评指正

 

public List<Object> SelectClassFS(Object tableClass)
        {
            string className = tableClass.ToString().Substring(tableClass.ToString().IndexOf('.') + 1);
            string tableName = className.Substring(0, className.LastIndexOf('D'));
            MethodInfo[] miClass;
            //Object milist = (Object)Activator.CreateInstance(tableClass.GetType());
            List<Object> reList = new List<Object>();

            OracleCommand Ocmd = new OracleCommand("select * from " + tableName);
            Ocmd.Connection = Oconn;
            OracleDataReader odr = Ocmd.ExecuteReader();

            while (odr.Read())
            {

                Type tp = tableClass.GetType();
                miClass = tp.GetMethods();
                Object mis = (Object) Activator.CreateInstance(tableClass.GetType());
                foreach (MethodInfo _mi in miClass)
                {

                    string memberName = _mi.Name.Substring(_mi.Name.IndexOf('_') + 1);
                    if (_mi.Name != "set_" + memberName) continue;
                    //MethodInfo __mi = tp.GetMethod(_mi.Name);
                    _mi.Invoke(mis, new object[] { odr[memberName].ToString() });
                   
                }
                reList.Add(mis);
            }
            Ocmd.Clone();
            return reList;
        }

posted @ 2009-05-19 09:11  chinaeddy  阅读(3613)  评论(2编辑  收藏  举报