C# 通过反射实现对象映射:将2个属性相近的对象相互转换
前言
我们在编程过程中,经常需要将一个对象转成另一个对象(一般称为对象映射)。
比如我们有2个类:
//第1个类 CLS1
class CLS1
{
public int i {get; set;}
public string str {get; set;}
}
//第2个类 CLS2
class CLS2
{
public int i {get; set;}
public string str {get; set;}
}
两个类都拥有属性 i 和 str。
当我们需要将 CLS1 的实例对象转化为 CLS2 的实例对象时,正常会这样操作:
CLS1 obj1 = new CLS1(){i = 1, str = "ss"};
CLS2 obj2 = new CLS2();
//将 obj1 映射为 obj2
obj2.i = obj1.i; //obj2.i = 1;
obj2.str = obj1.str; //obj2.str = "ss";
如果属性多了,写起来会很繁琐,希望可以通过一个方法自动帮我们解决,比如这样:
//将 CLS1 的对象映射为 CLS2 的对象
obj2 = Mapper.T1MapToT2<CLS1, CLS2>(obj1); //obj2.i = 1; obj2.str = "ss";
实现
以下是实现代码:
public class Mapper
{
/// <summary>
/// 通过反射,将 T1 映射为 T2
/// </summary>
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <param name="t1"></param>
/// <returns></returns>
public static T2 T1MapToT2<T1, T2>(T1 t1)
where T1 : class
where T2 : class //, new()
{
T2 t2 = Activator.CreateInstance<T2>(); //T2 t2 = new T2(); //后面这种写法,要在 where 中添加 new()
if (t1 == null)
{
return t2;
}
var p1 = t1.GetType().GetProperties();
var p2 = typeof(T2).GetProperties();
for (int i = 0; i < p1.Length; i++)
{
//条件:1、属性名相同;2、t2属性可写;3、属性可读性一致;4、数据类型相近(相同,或者接近。接近如:int 和 int?)
var p = p2.Where(t => t.Name == p1[i].Name && t.CanWrite && t.CanRead == p1[i].CanRead).FirstOrDefault();
if (p == null)
continue;
var v = p1[i].GetValue(t1);
if (v == null)
continue;
try { p.SetValue(t2, v); } //难判定数据类型,暂时这样处理
catch
{
try { p.SetValue(t2, Convert.ChangeType(v, p.PropertyType)); } //int? -> object -> int? 会抛错
catch { }
}
}
return t2;
}
//这种写法和上面的写法没啥差别
public static T2 T1MapToT2_2<T1, T2>(T1 t1)
where T1 : class
where T2 : class //, new()
{
T2 t2 = Activator.CreateInstance<T2>(); //T2 t2 = new T2(); //后面这种写法,要在 where 中添加 new()
var p1 = t1.GetType().GetProperties();
var p2 = typeof(T2);
for (int i = 0; i < p1.Length; i++)
{
//条件:1、属性名相同;2、t2属性可写;3、属性可读性一致;4、数据类型相近(相同,或者接近。接近如:int 和 int?)
var p = p2.GetProperty(p1[i].Name);
if (p == null || !p.CanWrite || p.CanRead != p1[i].CanRead)
continue;
var v = p1[i].GetValue(t1);
if (v == null)
continue;
try { p.SetValue(t2, Convert.ChangeType(v, p.PropertyType)); }
catch { }
}
return t2;
}
}
C# 通过反射实现对象映射:将2个属性相近的对象相互转换的更多相关文章
- Powermockito 针对方法中new 对象的模拟,以及属性中new 对象的模拟
PowerMocker 是一个功能逆天的mock 工具. 一,Powermockito 针对方法中new 对象的模拟 // 如何才能mock掉 WeChatConfigUtil 这个类,让 weCha ...
- Python与数据库[2] -> 关系对象映射/ORM[2] -> 建立声明层表对象的两种方式
建立声明层表对象的两种方式 在对表对象进行建立的时候,通常有两种方式可以完成,以下是两种方式的建立过程对比 首先导入需要的模块,获取一个声明层 from sqlalchemy.sql.schema i ...
- PHP设计模式笔记六:数据对象映射模式 -- Rango韩老师 http://www.imooc.com/learn/236
数据对象映射模式 1.数据对象映射模式,是将对象和数据存储映射起来,对一个对象的操作会映射为对数据存储的操作 2.在代码中实现数据对象映射模式,我们将实现一个ORM类,将复杂的SQL语句映射成对象属性 ...
- 处理Selection对象和Range对象——Word VBA中重要的两个对象
处理Selection对象和Range对象——Word VBA中重要的两个对象 Word 开发人员参考Selection 对象代表窗口或窗格中的当前所选内容.所选内容代表文档中选定(或突出显示)的区域 ...
- Android 学习笔记之AndBase框架学习(五) 数据库ORM..注解,数据库对象映射...
PS:好久没写博客了... 学习内容: 1.DAO介绍,通用DAO的简单调度过程.. 2.数据库映射关系... 3.使用泛型+反射+注解封装通用DAO.. 4.使用AndBase框架实现对DAO的调用 ...
- 关于对象映射(Dto->model) 思路的一些想法
最近粗浅的学习了下AutoMapper 这个做对象映射的第三方工具,觉得非常方便使用,所以简单的总结了一下我能想到的简单的对象映射的方式. 占时先不考虑源对象成员到目标对象成员的指定映射(即成员名不一 ...
- C# 高性能对象映射(表达式树实现)
前言 上篇简单实现了对象映射,针对数组,集合,嵌套类并没有给出实现,这一篇继续完善细节. 开源对象映射类库映射分析 1.AutoMapper 实现原理:主要通过表达式树Api 实现对象映射 优点: . ...
- ASP.NET CORE 中使用AutoMapper进行对象映射
ASP.NET CORE 中使用AutoMapper进行对象映射 1.什么是AutoMapper? AutoMapper是基于对象到对象约定的映射工具,常用于(但并不仅限制于)把复杂的对象模型转为DT ...
- Mybaits的中的对象映射(包含仅有基本数据类型的属性的和对象类型的属性的)
转:https://blog.csdn.net/cjt20100/article/details/46547617. 1 constructor – 用来将结果反射给一个实例化好的类的构造器 a ...
随机推荐
- python 01篇
一.Pycharm 使用小tips 1.1 pycharm创建项目时,选择Python环境,不使用默认的虚拟环境 1.2 如何在pycharm中查看python版本 路径:File-Settings- ...
- C语言:extern应用
前面我们都是将所有的代码写到一个源文件里面,对于小程序,代码不过几百行,这或许无可厚非,但当程序膨胀代码到几千行甚至上万行后,就应该考虑将代码分散到多个文件中,否则代码的阅读和维护将成为一件痛苦的事情 ...
- Java异常情况
从网上了解了这些Java异常,遇到过一些,大部分还没遇到: 1. SQLException:操作数据库异常类. 2. ClassCastException:数据类型转换异常. 3. NumberFor ...
- Linux服务器相关性能的命令
Linux服务器相关性能的命令 一.查看服务器性能信息的相关命令 1.cpu信息查看 cpu分为物理cpu和逻辑cpu 物理cpu:实际物理服务器插槽上cpu的个数,可以通过physical id不重 ...
- java网络编程基础——TCP网络编程二
1.半关闭的Socket 前面的服务器和客户端通信时总是以行为最小数据单位,但是在某些协议里,通信的数据单位可能是多行的,当出现多行数据时就 出现一个问题:Socket输出流如何表示输出数据已经结束. ...
- 关于如何在mysql中插入一条数据后,返回这条数据的id
简单的总结一下如何在mysql中出入一条数据后,返回该条数据的id ,假如之后代码需要这个id,这样做起来就变得非常方便,内容如下: <insert id="insertAndGetI ...
- Java多线程(上)
Java多线程 程序.进程和线程 一.程序 程序是存储在磁盘上, 包含可执行机器指令和数据的静态实体. 即进程或者任务是处于活动状态的计算机程序. 二.进程 进程是资源(CPU.内存等)分配的基本单位 ...
- 队列Queue:任务间的消息读写,安排起来~
摘要:本文通过分析鸿蒙轻内核队列模块的源码,掌握队列使用上的差异. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列十三 消息队列Queue>,作者:zhushy . 队列(Queue)是 ...
- div填满页面剩余空间的方法
想让div填满页面剩余空间,最简易的方式还是靠提前的布局. 这里提供两种方法: (1)利用 height 样式的%比例设置布局 <!DOCTYPE html> <html lang= ...
- kubernetes 降本增效标准指南|ProphetPilot:容器智能成本管理引擎
作者 田奇,腾讯云高级工程师,专注大规模离在线混部,弹性伸缩,云原生成本优化,熟悉Kubernetes,关注云原生大数据.AI. 王孝威,腾讯云容器产品经理,热衷于为客户提供高效的 Kubernete ...