C#通过反射实现两个对象相同属性值的复制

it2022-05-05  63

前言

在写程序的过程中经常遇到将一个对象中的属性值赋给另一个对象,一般情况下我们都是一个一个属性对应赋值,但是这样过于繁杂,并且当类的属性发生变化时,还要去修改对应关系。基于这种需求,我写了一个帮助类,方便大家复制属性值,有什么不足之处或者需要改进的地方希望大家指出,如有更好的方法还请赐教。

代码实现

下面就是代码,已加注释,不再赘述。ObjectCopy.cs

/// <summary> /// 对象属性值复制 /// </summary> public class ObjectCopy { /// <summary> /// 属性映射(静态对象,无需重复建立属性映射关系,提高效率) /// </summary> public static Dictionary<string, List<string>> MapDic = new Dictionary<string, List<string>>(); /// <summary> /// S复制到D(创建对象D) /// </summary> /// <typeparam name="D">输出对象类型</typeparam> /// <typeparam name="S">输入对象类型</typeparam> /// <param name="s">输入对象</param> /// <returns></returns> public static D Copy<S, D>(S s) where D : class, new() where S : class, new() { if (s == null) { return default(D); } //使用无参数构造函数,创建指定泛型类型参数所指定类型的实例 D d = Activator.CreateInstance<D>(); return Copy<S, D>(s, d); } /// <summary> /// S复制到D(对象D已存在) /// </summary> /// <typeparam name="D">输出对象类型</typeparam> /// <typeparam name="S">输入对象类型</typeparam> /// <param name="s">输入对象</param> /// <param name="d">输出对象</param> /// <returns></returns> public static D Copy<S, D>(S s,D d) where D: class, new() where S : class, new() { if (s==null||d==null) { return d; } try { var sType = s.GetType(); var dType = typeof(D); //属性映射Key string mapkey = dType.FullName + "_" + sType.FullName; if (MapDic.ContainsKey(mapkey)) { //已存在属性映射 foreach (var item in MapDic[mapkey]) { //按照属性映射关系赋值 //.net 4 dType.GetProperty(item).SetValue(d, sType.GetProperty(item).GetValue(s, null), null); //.net 4.5 //dType.GetProperty(item).SetValue(d, sType.GetProperty(item).GetValue(s)); } } else { //不存在属性映射,需要建立属性映射 List<string> namelist = new List<string>(); Dictionary<string, TypeAndValue> dic = new Dictionary<string, TypeAndValue>(); //遍历获取输入类型的属性(属性名称,类型,值) foreach (PropertyInfo sP in sType.GetProperties()) { //.net 4 dic.Add(sP.Name, new TypeAndValue() { type = sP.PropertyType, value = sP.GetValue(s, null) }); //.net 4.5 //dic.Add(sP.Name, new TypeAndValue() { type = sP.PropertyType, value = sP.GetValue(s) }); } //遍历输出类型的属性,并与输入类型(相同名称和类型的属性)建立映射,并赋值 foreach (PropertyInfo dP in dType.GetProperties()) { if (dic.Keys.Contains(dP.Name)) { if (dP.PropertyType == dic[dP.Name].type) { namelist.Add(dP.Name); //.net 4 dP.SetValue(d, dic[dP.Name].value, null); //.net 4.5 //dP.SetValue(d, dic[dP.Name].value); } } } //保存映射 if (!MapDic.ContainsKey(mapkey)) { MapDic.Add(mapkey, namelist); } } } catch (Exception ex) { Debug.Write(ex); } return d; } /// <summary> /// SList复制到DList /// </summary> /// <typeparam name="D">输出对象类型</typeparam> /// <typeparam name="S">输入对象类型</typeparam> /// <param name="sList">输入对象集合</param> /// <returns></returns> public static IQueryable<D> Copy<S, D>(IQueryable<S> sList) where D : class, new() where S : class, new() { List<D> dList = new List<D>(); foreach (var item in sList) { dList.Add(Copy<S, D>(item)); } return dList.AsQueryable(); } } /// <summary> /// 类型和值 /// </summary> class TypeAndValue { /// <summary> /// 类型 /// </summary> public Type type { get; set; } /// <summary> /// 值 /// </summary> public object value { get; set; } }

对于不同的框架有些地方的写法不同,代码中也已标注出来。

测试

下面我们创建一个控制台程序去测试一下Program.cs

class Program { static void Main(string[] args) { //创建类1的对象 Person1 p1 = new Person1() { ID = "10001", Name = "人类1号", Age = 18, Gender = "男" }; Console.WriteLine("p1"); p1.Write(); Console.WriteLine(""); //类1的值给类2(创建类2对象) Person2 p21 = ObjectCopy.Copy<Person1, Person2>(p1); Console.WriteLine("p21"); p21.Write(); Console.WriteLine(""); //类1的值给类2(类2已存在) Person2 p22 = new Person2(); p22.Address = "中国"; ObjectCopy.Copy<Person1, Person2>(p1, p22); Console.WriteLine("p22"); p22.Write(); Console.ReadLine(); } } /// <summary> /// 测试类1 /// </summary> class Person1 { public string ID { get; set; } public string Name { get; set; } public int Age { get; set; } public string Gender { get; set; } public virtual void Write() { Console.WriteLine("ID:" + this.ID); Console.WriteLine("Name:" + this.Name); Console.WriteLine("Age:" + this.Age); Console.WriteLine("Gender:" + this.Gender); } } /// <summary> /// 测试类2 /// </summary> class Person2: Person1 { public string Address { get; set; } public override void Write() { base.Write(); Console.WriteLine("Address:" + this.Address); } }

输出结果:

代码下载

链接:http://pan.baidu.com/s/1jIBZ91G 密码:8z5e

转载于:https://www.cnblogs.com/ArtlessBruin/p/8126413.html


最新回复(0)