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

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

常规属性

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

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

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自动实现的属性上可以使用特性,不能用在支持后备字段上。 如果属性的后备字段上使用特性,则应该只创建常规属性。
        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);

C#中属性PropertyInfo的使用的更多相关文章

  1. VB类模块中属性的参数——VBA中Range对象的Value属性和Value2属性的一点区别

    在VB中,属性是可以有参数的,而VBA中属性使用参数非常常见.比如最常用的:Worksheet.Range("A1:A10")  VB的语法,使用参数的不一定是方法,也有可能是属性 ...

  2. [原创]java WEB学习笔记48:其他的Servlet 监听器:域对象中属性的变更的事件监听器 (3 个),感知 Session 绑定的事件监听器(2个)

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  3. 为什么Nhibernate中属性和方法必须Virtual的

    如果你曾经用过NHibernate 2.0或者更高的版本,那您一定碰到过下面的错误:NHibernate.InvalidProxyTypeException: The following types ...

  4. [Tips]ASP.NET MVC 发布到服务器后Model中属性相关的Attribute失效

    Asp.net MVC4 开发的项目,发布到真实环境环境后Model中的一个属性设置的了Attribute,但是这些Attribute都失效. 经过对比和坚持代码发现控制长度的Attribute使用错 ...

  5. 坑爹的vector iterators incompatible错误(VS中属性页-->C/C++-->代码生成-->>运行库)

    之前一直被这个错误折磨着,就是不知道问题在那,后来找了很多资料,大概都是说这是因为多个线程同时操作vector的问题(参考这里).可是我这里的代码并没有问题,因为同样的代码在别的解决方案中已经成功运行 ...

  6. <mate>标签中属性/值的各个意思

    <mate>标签中属性/值的各个意思 HTML 4 name 属性 1.<mate name="author" content="" /> ...

  7. Flex的 Event中属性currentTarget与target的区别

    Flex的 Event中属性currentTarget与target的区别 1.区别 (1)currentTarget是事件的处理对象(event processor) (2)target是事件的调用 ...

  8. 【JVM虚拟机】(7)---深入理解Class中-属性集合

    #[JVM虚拟机](7)---深入理解Class中-属性集合 之前有关class文件已经写了两篇博客: 1.[JVM虚拟机](5)---深入理解JVM-Class中常量池 2.[JVM虚拟机](6)- ...

  9. C# 求链表 list 中 属性的 最大值 最小值

    获取链表List中对象属性最大值最小值(Max,Min)的方法: 1.创建一个类,类中有一个属性A /// <summary> /// 用于测试属性的类 /// </summary& ...

随机推荐

  1. Ext.example.msg()应用

    ①需要在开发包中包含文件夹example/shared中的example.js和example.css两个文件即可. ②在html文件中引入: <script src="../extj ...

  2. java_String、StringBuilder

    在介绍String和StringBuilder前先学习一下equals方法和toString方法.API java1.6提取码:04b6 equals方法 equals方法,用于比较两个对象是否相同, ...

  3. IdentityServer4之JWT签名(RSA加密证书)及验签

    一.前言 在IdentityServer4中有两种令牌,一个是JWT和Reference Token,在IDS4中默认用的是JWT,那么这两者有什么区别呢? 二.JWT与Reference Token ...

  4. shell rename directory

    mv can do two jobs. It can move files or directories It can rename files or directories To just rena ...

  5. 求N!末尾所得数字0的个数

    题目:给定一个整数N ,那么N 的阶乘N !末尾有多少个0呢? 例如:N = 10,N! = 3628800,所以N!末尾就有2个零. 分析:如果直接先算出N!阶乘,很容易导致内存溢出.显然,直接算出 ...

  6. 顺序线性表之大整数求和C++实现

    顺序线性表之大整数求和 大整数求和伪代码 1.初始化进位标志 flag=0: 2.求大整数 A 和 B 的长度: int aLength = a.GetLength(); int bLength = ...

  7. 洛谷.4383.[八省联考2018]林克卡特树lct(树形DP 带权二分)

    题目链接 \(Description\) 给定一棵边带权的树.求删掉K条边.再连上K条权为0的边后,新树的最大直径. \(n,K\leq3\times10^5\). \(Solution\) 题目可以 ...

  8. java的多线程之四(线程的操作)

    本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/17560467,转载请注明. 线程中断    线程中断涉及到三个方法,如下 ...

  9. Java-----jar反编译修改重新打包

    http://blog.csdn.net/hekewangzi/article/details/44676797 一.使用反编译工具JD-GUI(JD-GUI相关操作见Java-----反编译clas ...

  10. wikioi 1080 线段树练习 树状数组

    1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond       题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现 ...