前言: 两年前写过一个 反射实现不同模型相同属性赋值 只能简单的实现两个model 相同属性名,相同类型赋值

最近又遇到这个问题,需要对相同属性名或者指定属性名 不同类型(复杂对象,如:List<class1> 到list<class2>)对象赋值,所有之前的代码就不能用了

花了点时间把这个代码给完善了点点


需求:1.对不同model中的相同属性名赋值 如:Class1中Name 赋值到 Class2中Name

2.对不同model中的不同属性名赋值 如:Class1中Name 赋值到 Class2中Uname

3.对不同model中的相同属性名(集合对象)赋值,集合对象赋值要分4种情况

     3.1.两个model中集合对象都是List集合  如:Class1中List<User1> 赋值到 Class2中List<User2>

     3.2.两个model中集合对象都是数组(Array)  如:Class1中User1[] 赋值到 Class2中User2[]

3.3.一个model中是List,一个里面是Array  如:Class1中List<User1> 赋值到 Class2中User2[]

3.4.一个model中是Array,一个是List  如:Class1中User1[] 赋值到 List<User2>
大概需求就是如上,不考虑基础数据类型转换,如:Class1中Time(数据类型String)  到 Class2中Time(数据类型Datetime)

这里不再对需求1进行讨论,可以直接使用两年前写的


话不多说,先贴代码,再解释.

1.常量

  1. private static readonly string ListTypeName = typeof (List<>).Name; //用于判定是否是List集合

2.主函数

  1. /// <summary>
  2. /// 模型赋值
  3. /// </summary>
  4. /// <param name="source">数据源模型</param>
  5. /// <param name="target">目标模型</param>
  6. /// <param name="pars">数据源模型指定属性值 赋值 到目标模型指定属性,例:Key=Name,Value=Uname 把数据模型Name属性赋给目标模型Uname</param>
  7. public static void CopyModel(object source, object target, Dictionary<string, string> pars)
  8. {
  9. //获取Type
  10. Type ttarget = target.GetType();
  11. Type tsource = source.GetType();
  12.  
  13. //根据 数据模型 来对 目标模型 赋值
  14. //循环数据模型所有公共属性
  15. foreach (var sourceAttr in tsource.GetProperties())
  16. {
  17. //pars.ContainsKey(sourceAttr.Name) 得到不同属性名,用来实现 数据模型Name属性赋给目标模型Uname
  18. PropertyInfo targetAttr = ttarget.GetProperty(pars.ContainsKey(sourceAttr.Name) ? pars[sourceAttr.Name] : sourceAttr.Name);//获取目标模型属性Name==数据模型属性Name(得到目标属性)
  19. if (targetAttr == null) //为null标识目标模型中没有该属性,进入下次循环
  20. continue;
  21. try
  22. {
  23. //获取两个model属性类型
  24. var targetProType = targetAttr.PropertyType;
  25. var sourceProType = sourceAttr.PropertyType;
  26. //list->list 判断两个属性类型是否为list
  27. if (targetProType.Name == ListTypeName && sourceProType.Name == ListTypeName)
  28. {
  29. var miValue = (IList)sourceAttr.GetValue(source, null); //得到数据模型中该属性的数据,直接转为IList
  30. CopeToList(miValue, target, pars, targetAttr); //调用赋值
  31. return;
  32. }
  33. //array->array 判断两个属性类型是否为array
  34. if (targetProType.IsArray && sourceProType.IsArray)
  35. {
  36. var miValue = (Array)sourceAttr.GetValue(source, null); //得到数据模型中该属性的数据,直接转为Array
  37. CopyToArray(miValue, miValue.Length, target, pars, targetAttr); //调用赋值
  38. return;
  39. }
  40. //list->array 当数据属性类型为List 目标属性类型为Array
  41. if (targetProType.IsArray && sourceProType.Name == ListTypeName)
  42. {
  43. var miValue = (IList)sourceAttr.GetValue(source, null); //得到数据模型中该属性的数据,直接转为IList
  44. CopyToArray(miValue, miValue.Count, target, pars, targetAttr); //调用赋值
  45. return;
  46. }
  47. //array->list 当数据属性类型为Array 目标属性类型为List
  48. if (targetProType.Name == ListTypeName && sourceProType.IsArray)
  49. {
  50. var miValue = (Array)sourceAttr.GetValue(source, null); //得到数据模型中该属性的数据,直接转为Array
  51. CopeToList(miValue, target, pars, targetAttr); //调用赋值
  52. return;
  53. }
  54. //基础数据类型赋值
  55. var s = sourceAttr.GetValue(source, null);
  56. targetAttr.SetValue(target, s, null);
  57. }
  58. catch
  59. {
  60. }
  61. }
  62. }

3.CopeToList

  1. /// <summary>
  2. /// 集合数据赋值 赋值到List
  3. /// </summary>
  4. /// <param name="data">数据集合</param>
  5. /// <param name="target">目标模型</param>
  6. /// <param name="pars">数据源模型指定属性值 赋值 到目标模型指定属性</param>
  7. /// <param name="targetAttr">目标属性</param>
  8. private static void CopeToList(IEnumerable data, object target, Dictionary<string, string> pars, PropertyInfo targetAttr)
  9. {
  10. if (data == null)
  11. return;
  12. //获取目标属性类型
  13. var targetProType = targetAttr.PropertyType;
  14.  
  15. //得到目标属性值
  16. var desValue = (IList)targetAttr.GetValue(target, null);
  17. if (desValue == null) //如果List为null 需要new List<T>();
  18. {
  19. var newlist = Activator.CreateInstance(targetProType); //根据目标属性类型实例化List,如:目标属性为List<Class1>
  20. targetAttr.SetValue(target, newlist, null); //把newlist写入(赋值)目标属性
  21. desValue = (IList)targetAttr.GetValue(target, null); //再次获取目标属性值
  22. }
  23. var desMethod = targetProType.GetMethod("Add"); //获取到List.Add方法
  24. var modelType = targetProType.GetGenericArguments()[]; //获取List<T>中 T的类型
  25. foreach (var v in data) //循环数据集合
  26. {
  27. var model = Activator.CreateInstance(modelType); //创建T实例
  28. CopyModel(v, model, pars); //调用模式赋值
  29. desMethod.Invoke(desValue, new[] { model }); //调用List.Add方法,将数据对象Add到目标属性(List)中
  30. }
  31. }

4.CopyToArray

  1. /// <summary>
  2. /// 集合数据赋值 赋值到数组(Array)
  3. /// </summary>
  4. /// <param name="data">数据集合</param>
  5. /// <param name="count">数据条数(由于IEnumerable不方便获取数据条数,所有这里通过外面传入参数)</param>
  6. /// <param name="target">目标模型</param>
  7. /// <param name="pars">数据源模型指定属性值 赋值 到目标模型指定属性</param>
  8. /// <param name="targetAttr">目标属性</param>
  9. private static void CopyToArray(IEnumerable data,int count, object target, Dictionary<string, string> pars, PropertyInfo targetAttr)
  10. {
  11. if (data == null)
  12. return;
  13. //获取目标属性类型
  14. var targetProType = targetAttr.PropertyType;
  15.  
  16. var arr = Type.GetType(targetProType.FullName); //根据目标数组对象实例化心的数组对象
  17. var newarr = (Array)arr.InvokeMember("Set", BindingFlags.CreateInstance, null, arr, new object[] { count }); //调用数组Set方法设置数组长度,长度为count
  18. var modelType = Type.GetType(targetProType.FullName.Replace("[]", "")); //获取数组元素类型
  19. int c = ; //用来为数组数据位置定位
  20. foreach (var v in data)
  21. {
  22. var model = Activator.CreateInstance(modelType); //实例化数组元素对象
  23. CopyModel(v, model, pars); //调用赋值
  24. newarr.SetValue(model, c); //用SetValue方法进行赋值
  25. c++;
  26. }
  27. targetAttr.SetValue(target, newarr, null); //将新数组直接赋值到目标属性
  28. }

解释

上面代码注释应该还算比较详细吧,下面就来列举上面代码的使用

需求1.这个就不举例子了,应该很好理解

需求2.

model:

  1. public class User1
  2. {
  3. public string Name{ get; set; }
  4. }
  5.  
  6. public class User2
  7. {
  8. public string Uname { get; set; }
  9. }

用法:

  1. User1 u1 = new User1 {Name="tom"}
  2. User2 u2 = new User2 ();
  3. Dictionary<string, string> dic = new Dictionary<string, string>();
  4. dic.Add("Name","Uname")
  5. CopyModel(u1,u2, dic);

需求3.1.
model:

  1. public class User1
  2. {
  3. public List<Test> Test { get; set; }
  4. }
  5.  
  6. public class User2
  7. {
  8. public List<Test2> Test { get; set; }
  9. }
  10.  
  11. public class Test
  12. {
  13. public string Name { get; set; }
  14. }
  15. public class Test2
  16. {
  17. public string Name { get; set; }
  18. }

用法:

  1. User1 u1 = new User1 ();
  2. u1.Test = new List<Test>();
  3. u1.Test.Add(new Test { Name = ""});
  4. u1.Test.Add(new Test { Name = "" });
  5. u1.Test.Add(new Test {Name = ""});
  6. User2 u2 = new User2();
  7.  
  8. Dictionary<string, string> dic = new Dictionary<string, string>();
  9. CopyModel(u1,u2, dic);

需求3.2

model:

  1. public class User1
  2. {
  3. public Test[] Test { get; set; }
  4. }
  5.  
  6. public class User2
  7. {
  8. public Test2[] Test { get; set; }
  9. }

用法:同上

需求3.3:

model:

  1. public class User1
  2. {
  3. public List<Test> Test { get; set; }
  4. }
  5.  
  6. public class User2
  7. {
  8. public Test2[] Test { get; set; }
  9. }

用法:同上

需求3.4:

  1. public class User1
  2. {
  3. public Test2[] Test { get; set; }
  4. }
  5.  
  6. public class User2
  7. {
  8. public List<Test> Test { get; set; }
  9. }

同法:同上


总结:大致需求就是解决上述模型赋值问题,此方法由于赋值调用自身,可以实现无限下级模型赋值 如:User1.Test为复杂对象集合,Test类中也有复杂集合对象,无限让下执行

   对与复杂集合内不同属性赋值也通过Dictionary传入, 如:User1.Test中Test.Name 赋值到Test2.Uname

我不晓得我表述清楚没有,反正大家慢慢看吧(我的错别字也是不太多,别介意→_→ )

原帖地址:http://www.cnblogs.com/jio92/p/CopyModel.html

反射 实现不同模型相同属性赋值 第二集(automapper)的更多相关文章

  1. Android利用反射机制为实体类属性赋值

    在做android项目时,有时会遇到从网络上获取json类型数据,赋值给实体类,实体类属性少可以一个一个的赋值,如果实体类有很多属性,赋值可能就要耗很长的功夫了,幸好Java给我们提供了反射机制.下面 ...

  2. 31 反射方式给类的属性赋值 和 对象赋值(clone)

    1.配置类 package com.da.tool.util.configuration.reflect; /** */ public class JobInfo { private String j ...

  3. Spring IoC 属性赋值阶段

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 容 ...

  4. Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值

    Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值 说到循环遍历,最常见的遍历数组/列表.Map等.但是,在开发过程中,有时需要循环遍历一个对象的所有属性.遍历对象的属性该如何遍历呢?查了 ...

  5. 用反射的形式将一个对象属性值赋值给另一个对象,省略点get/set方法的冗余代码

    1.本例使用的是idea 首先需要在idea中安装lombok插件,省略getter和setter方法的书写 在maven项目中加入lombok依赖 <dependency> <gr ...

  6. xml 转换成对象(采用反射机制对对对象属性赋值)

    /// <summary> /// 采用反射机制对对对象属性赋值 /// </summary> /// <param name="node">& ...

  7. 【Java EE 学习 69 上】【struts2】【paramsPrepareParamsStack拦截器栈解决model对象和属性赋值冲突问题】

    昨天有同学问我问题,他告诉我他的Action中的一个属性明明提供了get/set方法,但是在方法中却获取不到表单中传递过来的值.代码如下(简化后的代码) public class UserAction ...

  8. 反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性、字段),而不去使用Invoke方法)

    反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性.字段),而不去使用Invoke方法)   创建Delegate (1).Delegate.CreateDelegate(Type, ...

  9. Spring笔记04(DI(给属性赋值),自动装配(autowire))

    给不同数据类型注入值: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="h ...

随机推荐

  1. 关于InnoDB的Next-Key lock

    最近一段时间在准备新员工培训的材料,本来打算介绍介绍概念就OK的,但是既然写了事务的章节,就特别想介绍一下锁,介绍了锁,就忍不住想介绍一下Next-Key Lock. 大家知道,标准的事务隔离级别有R ...

  2. DGbroker主备切换

    1.检查DG是否正常 DGMGRL> show configuration; Configuration - dgc Protection Mode: MaxProtection Databas ...

  3. monkeyrunner之安卓开发环境搭建(一)

    在学习monkeyrunner之前,让我们先搭建好eclipse安卓开发环境. 对于程序开发人员而言,eclipse并不陌生,它提供了一个非常广阔的平台来开发程序.同样也可以用它来开发android程 ...

  4. linux tar命令简介

    一.使用介绍 1.名词区分 打包:将一大堆文件或目录变成一个总的文件[tar命令] 压缩:将一个大的文件通过一些压缩算法变成一个小文件[gzip,bzip2等] Linux中很多压缩程序只能针对一个文 ...

  5. Codeforces Round #286 Div.1 A Mr. Kitayuta, the Treasure Hunter --DP

    题意:0~30000有30001个地方,每个地方有一个或多个金币,第一步走到了d,步长为d,以后走的步长可以是上次步长+1,-1或不变,走到某个地方可以收集那个地方的财富,现在问走出去(>300 ...

  6. Android驱动入门-Led控制+app+ndk库+底层驱动

    硬件平台: FriendlyARM Tiny4412 Cortex-A9 操作系统: UBUNTU 14.04 LTS 时间:2016-09-20  21:56:48 本次实验使用的是 安卓APP + ...

  7. [No00001B]到底如何培养语感?

  8. Git版本恢复命令reset(转载)

    本博文转载自:http://www.tech126.com/git-reset/: 如果看不懂的话,请在git下练习,如果练习后任然有不懂的,可以留言也可以发送邮件到luoquantao@126.co ...

  9. 一个App需要的东西

    1.短信申请平台  (发送验证码需要的短信) http://www.yuntongxun.com/api/sms?nl=sy_cp  容联云通讯

  10. 一种Docker image镜像的取代方案

    在http://openvz.org/Download/templates/precreated中有很多压缩的镜像文件,可以将这些文件下载后采用import方式使用镜像,也可以采用我原来的博文:doc ...