C#中属性PropertyInfo的使用_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > C#中属性PropertyInfo的使用

C#中属性PropertyInfo的使用

 2014/10/13 18:32:00  Fly_Elephant  程序员俱乐部  我要评论(0)
  • 摘要:昨天编程遇到一个问题两个类字段都是二十多个,其中有十多个是相同的,需要将一个类的字段赋值给另外一个类,开始的自己想手动的一个个去赋值,后来想来一下C#基础知识,用PropertyInfo就可以解决类似的问题,博客园写博客需要内容详实,我还是慢慢的C#属性从头写起,先看下属性的定义吧:属性定义:它提供灵活的机制来读取、编写或计算某个私有字段的值。可以像使用公共数据成员一样使用属性,但实际上它们是称作“访问器”的特殊方法。这使得可以轻松访问数据
  • 标签:C# 使用

昨天编程遇到一个问题两个类字段都是二十多个,其中有十多个是相同的,需要将一个类的字段赋值给另外一个类,开始的自己想手动的一个个去赋值,后来想来一下C#基础知识,用PropertyInfo就可以解决类似的问题,博客园写博客需要内容详实,我还是慢慢的C#属性从头写起,先看下属性的定义吧:

属性定义:它提供灵活的机制来读取、编写或计算某个私有字段的值。 可以像使用公共数据成员一样使用属性,但实际上它们是称作“访问器”的特殊方法。 这使得可以轻松访问数据,此外还有助于提高方法的安全性和灵活性。属性通常可以分为常规属性和自动属性。两者之间还是有一点区别的,最开始编程对着两个全无概念。

常规属性

 常规属性以前做Winform的时候经常使用,现在开始使用EF,基本上都是使用自动属性,看下常规属性的完成构成:

1.私有字段,一般设置为私有,通过属性来赋值保证起安全性:

class="brush:csharp;gutter:true;">private string _age;

2.get访问器,负责读取数据,其中可以进行自己的逻辑判断和数据验证,以return或者throw结束:

           get 
            {
                //年龄返回值判断
                return _age> 0 ? _age: 0;
            }

3.set访问器,负责给属性赋值,类似于一个返回类型为void的方法,可以包含逻辑处理,例如可以根据默认的值通过计算后返回结果。

自动属性

   上面简单的说了一下常规属性,当属性访问器中不需要其他逻辑时,可以使用自动属性,不过需要注意一点的就是声明自动属性时,编译器将创建一个私有的匿名后备字段,该字段只能通过属性的 get 和 set 访问器进行访问。

 public int Id { get; set; }

自动属性没有太多可以可以说的东西,简单的对比一下常规属性和自动属性之间的区别吧:

        1.自动实现的属性必须同时声明 get 和 set 访问器。创建 readonly 自动实现属性时,需要将set 访问器设置为private 。

        2.自动实现的属性 (Property) 不允许具有属性 (Attribute)。如果必须在属性 (Property) 的后备字段上使用属性 (Attribute),则应该只创建常规属性 (Property)。
        3.自动实现属性get,和set中不能包含特殊的逻辑处理。与字段类似,但不同于字段。与字段不同,属性不作为变量来分类,不能将属性作为 ref参数或 out参数传递。

属性PropertyInfo的使用

 上面大概简单的说了一下属性和自动属性之间的区别,现在可以回归到文中最开始的时候的那个问题:

1.案例1,如果两个类中有大部分的字段相同,需要将其中一个类的字段赋值给另外一个类:

定义Person类:

 public class Person {
        public Person(int id,string name,string address)
        {
            this.Id = id;
            this.Name = name;
            this.Address = address;
        }
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
    }

 定义User类

 public class User {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Group { get; set; }
    }

 转换方法:

 public static User ConvertObject(User user,Person person)
        {
            PropertyInfo[] userPro = user.GetType().GetProperties();
            PropertyInfo[] personPro = person.GetType().GetProperties();
            if (userPro.Length>0&&personPro.Length>0)
            {
                for (int i = 0; i < userPro.Length; i++)
                {
                    for (int j = 0; j < personPro.Length; j++)
                    {
              //判断User的属性是不是的Person中 if (userPro[i].Name == personPro[j].Name && userPro[i].PropertyType == personPro[j].PropertyType) { Object value=personPro[j].GetValue(person, null);   //将Person中属性的值赋值给User
                userPro[i].SetValue(user,value , null); } } } } return user; }

 方法的调用:

  static void Main(string[] args)
        {
            Person person = new Person(1,"FlyElephant","北京");
            User user = new User();
            user.Id = 20;
            user = ConvertObject(user, person);
            Console.WriteLine("Id:" + user.Id + "Name:" + user.Name + "角色:" + user.Group);
            System.Console.Read();
        }
       

2.之前在做Winform的时候就经常回使用到SqlHelper,现在也有很多公司是这么使用的,当时很多东西感觉就是重复性的操作,一度以为编程只是复制粘贴,下面这段代码大家应该很常见:

            List<Person> list = new List<Person>();
            SqlDataReader sdr = new SqlDataReader();
            while (sdr.Read())
            {
                Person person = new Person();
                person.Name = sdr.GetString(0);
                //....下面类似
                list.Add(person);
            }
               

开始写的时候觉得是锻炼了,写的多了就觉得无聊了,其实完全可以换一种方式来实现上面的代码:

   public static List<T> ConvertData<T>(SqlDataReader sdr)
        {
            List<T> list = new List<T>();
            Type type = typeof(T);
            PropertyInfo[] properties = type.GetProperties();
            while (sdr.Read())
            {
                T model = Activator.CreateInstance<T>();
                for (int i = 0; i < properties.Length; i++)
                {
                    for (int j = 0; j < sdr.FieldCount; j++)
                    {
                        //判断属性的名称和字段的名称是否相同
                        if (properties[i].Name == sdr.GetName(j))
                        {
                            Object value =sdr[j];
                            //将字段的值赋值给User中的属性
                            properties[i].SetValue(model, value, null);
                        }
                    }
                }
                list.Add(model);
            }
            return list;
        }

 

List<User> list = new List<User>();
SqlDataReader sdr = cmd.ExecuteReader();
list = ConvertData<User>(sdr);

3.案例三,ajax页面传递值可以使用get方式,或者post方式的传递JSON格式数据转换

 

 简单的转换一个get传递的字符串Name=xx&Age=xx,后台直接用一个字典去模拟了:

 

            Dictionary<string, object> dic = new Dictionary<string, object>();
            dic.Add("Id",100);
            dic.Add("Name", "keso");
            dic.Add("Group", "程序员");

 

 转换字典方法:

 

  public static T ConvertDic<T>(Dictionary<string, object> dic)
        {
            T model = Activator.CreateInstance<T>();
            PropertyInfo[] modelPro = model.GetType().GetProperties();
            if (modelPro.Length > 0 && dic.Count() > 0)
            {
                for (int i = 0; i < modelPro.Length; i++)
                {
                    if (dic.ContainsKey(modelPro[i].Name))
                    {
                        modelPro[i].SetValue(model, dic[modelPro[i].Name], null);
                    }
                }
            }
            return model;
        }

 

  最后的调用:

 

User user = ConvertDic<User>(dic);

 

 评论中有园友提示了一下,如果是JSON的话大概是类似的,以前同事这样弄过,JSON解析可以下载一个JSON.NET,http://json.codeplex.com/,简单的调用:

            string jsonText = @"{""Name"" : ""keso"", ""Age"" : ""25""}";
            JObject jo = JObject.Parse(jsonText);
           string[] property = jo.Properties().Select(item=>item.Name.ToString()).ToArray();

  如果转换成一个类还是挺简单的,本文已经做了一部分修改,不知道为什么被人点了反对,写这篇文章本人还是花了心思,用了时间的,又不是口水文,如果你觉得我技术不到家可以提醒一下,请尊重别人的劳动成果,谢谢~

发表评论
用户名: 匿名