c#判断两个对象和对象中的属性是否相同(以及记录对象中的哪些字段,和详细的改变情况)
当前项目需要记录变更记录,即用户在进行编辑后,将变更操作记录下来。但是数据没有发生变化,则不记录。
代码1:(仅仅返回是否变化的标识)
/// <summary>
/// 反射对比实体属性变更
/// </summary>
/// <typeparam name="T"></typeparam>
public class CompareEntry<T>
{
/// <summary>
/// 编辑之前的对象和编辑后的对象进行对比
/// </summary>
/// <returns></returns>
public bool CompareDTO(T BeforeDTO, T AfterDTO)
{
bool IsEqual = true; if (BeforeDTO == null || AfterDTO == null)
{
IsEqual = false;
}
else if (BeforeDTO.Equals(DBNull.Value) || AfterDTO.Equals(DBNull.Value))
{
IsEqual = false;
}else if (BeforeDTO.GetType() != AfterDTO.GetType())
{
IsEqual = false;
return IsEqual;
}
else if (BeforeDTO is int || BeforeDTO is short || BeforeDTO is long || BeforeDTO is float || BeforeDTO is double || BeforeDTO is decimal)
{
//int 01与1
if (BeforeDTO is int)
{
if (Convert.ToInt32(BeforeDTO) != Convert.ToInt32(AfterDTO))
{
IsEqual = false;
}
}
else if (BeforeDTO is short)
{
if (Convert.ToInt16(BeforeDTO) != Convert.ToInt16(AfterDTO))
{
IsEqual = false;
}
}
else if (BeforeDTO is long)
{
if (Convert.ToInt64(BeforeDTO) != Convert.ToInt64(AfterDTO))
{
IsEqual = false;
}
}
else if (BeforeDTO is float)
{
if (Convert.ToSingle(BeforeDTO) != Convert.ToSingle(AfterDTO))
{
IsEqual = false;
}
}
else if (BeforeDTO is double)
{
if (Convert.ToDouble(BeforeDTO) != Convert.ToDouble(AfterDTO))
{
IsEqual = false;
}
}
else if (BeforeDTO is decimal)
{
if (Convert.ToDecimal(BeforeDTO) == Convert.ToDecimal(AfterDTO))
{
IsEqual = false;
}
}
}
else
{
var beforeMembers = BeforeDTO.GetType().GetProperties();
var afterMembers = AfterDTO.GetType().GetProperties();
for (int i = ; i < beforeMembers.Length; i++)
{
var beforeVal = beforeMembers[i].GetValue(BeforeDTO, null);
var afterVal = afterMembers[i].GetValue(AfterDTO, null);
var beforeValue = beforeVal == null ? null : beforeVal.ToString();
var afterValue = afterVal == null ? null : afterVal.ToString();
if (beforeValue != afterValue)
{
IsEqual = false;
break;
}
}
} return IsEqual;
}
}
调整后的代码:(返回标识以及详细变更记录)
/// <summary>
///
/// </summary>
public class CompareResult
{
/// <summary>
///
/// </summary>
public bool IsChange { get; set; }
/// <summary>
/// 变跟内容
/// </summary>
public string ChangeContent { get; set; }
} /// <summary>
/// 对比实体属性变更(利用反射)
/// </summary>
public class CompareEntry
{
/// <summary>
///
/// </summary>
/// <returns></returns>
public CompareResult CompareDTO(object BeforeDTO, object AfterDTO)
{
CompareResult result = new CompareResult();
bool b = false; if (BeforeDTO == null && AfterDTO != null)
{
b = true;
}
else if (BeforeDTO != null && AfterDTO == null)
{
b = true;
}
else if (BeforeDTO.Equals(DBNull.Value) && !AfterDTO.Equals(DBNull.Value))
{
b = true;
}
else if (!BeforeDTO.Equals(DBNull.Value) && AfterDTO.Equals(DBNull.Value))
{
b = true;
}
else if (BeforeDTO.GetType() != AfterDTO.GetType())
{
result.IsChange = true;
return result;
}
else if (BeforeDTO is int || BeforeDTO is short || BeforeDTO is long || BeforeDTO is float || BeforeDTO is double || BeforeDTO is decimal)
{
if (BeforeDTO is int)
{
if (Convert.ToInt32(BeforeDTO) != Convert.ToInt32(AfterDTO))
{
b = true;
}
}
else if (BeforeDTO is short)
{
if (Convert.ToInt16(BeforeDTO) != Convert.ToInt16(AfterDTO))
{
b = true;
}
}
else if (BeforeDTO is long)
{
if (Convert.ToInt64(BeforeDTO) != Convert.ToInt64(AfterDTO))
{
b = true;
}
}
else if (BeforeDTO is float)
{
if (Convert.ToSingle(BeforeDTO) != Convert.ToSingle(AfterDTO))
{
b = true;
}
}
else if (BeforeDTO is double)
{
if (Convert.ToDouble(BeforeDTO) != Convert.ToDouble(AfterDTO))
{
b = true;
}
}
else if (BeforeDTO is decimal)
{
if (Convert.ToDecimal(BeforeDTO) == Convert.ToDecimal(AfterDTO))
{
b = true;
}
}
}
else
{
StringBuilder content = new StringBuilder();
var beforeMembers = BeforeDTO.GetType().GetProperties();
var afterMembers = AfterDTO.GetType().GetProperties();
for (int i = ; i < beforeMembers.Length; i++)
{
var beforeVal = beforeMembers[i].GetValue(BeforeDTO, null);
var afterVal = afterMembers[i].GetValue(AfterDTO, null);
var beforeValue = beforeVal == null ? null : beforeVal.ToString();
var afterValue = afterVal == null ? null : afterVal.ToString();
if (beforeValue != afterValue)
{
b = true;
content.Append(beforeMembers[i].Name+"("+ beforeValue+"->"+afterValue+")");
}
}
result.IsChange = b;
result.ChangeContent = content.ToString();
} return result;
}
}
注意,引用类型进行对比的时候,需要在编辑之前对对象进行拷贝,让拷贝的对象与编辑后的对象进行对比。(因为引用类型不同于值类型,值类型每次操作都会产生一个新的对象,而引用类型在new一个新对象赋值时,其实是在堆上创建了一个内存地址,指向的仍然是原对象,对它操作原对象也会发生变化。所以只有通过拷贝复制一个新对象)
c#判断两个对象和对象中的属性是否相同(以及记录对象中的哪些字段,和详细的改变情况)的更多相关文章
- 将source类中的属性值赋给target类中对应的属性
/** * 对象的属性值拷贝 * <p> * 将source对象中的属性值赋值到target对象中的属性,属性名一样,类型一样 * <p> * example: * <p ...
- LinearLayout的gravity属性以及其子元素的layout_gravity何时有效;RelativeLayout如何调整其子元素位置只能用子元素中的属性来控制,用RelativeLayout中的gravity无法控制!!!
LinearLayout的gravity属性以及其子元素的layout_gravity何时有效:RelativeLayout如何调整其子元素位置只能用子元素中的属性来控制,用RelativeLayou ...
- 微信小程序:给data中对象中的属性设置值与给data中的属性或对象或数组设置值的区别
一.给data中的属性或对象或数组设置值,属性名不需要加引号 this.setData({ material: param, // 这里material为对象 } this.setData({ d ...
- 修改表单元素中placeholder属性样式、清除IE浏览器中input元素的清除图标和眼睛图标
一.修改input元素placeholder属性样式 在做项目的时候,一般表单元素的placeholder属性样式都是使用浏览器默认的,但有时候为了追求设计上的美感需要修表单元素的placeholde ...
- 用泛型方法Java从实体中提取属性值,以及在泛型方法中的使用
public <T> T getFieldValue(Object target, String fieldName, Class<T> typeName) { try { O ...
- JavaScript 深入了解对象中的属性
本篇主要介绍JS中对象的属性,包括:属性的分类.访问方式.检测属性.遍历属性以及属性特性等内容. 目录 1. 介绍:描述属性的命名方式.查找路径以及分类 2. 属性的访问方式:介绍'.'访问方式.'[ ...
- 在 WPF 中获取一个依赖对象的所有依赖项属性
原文:在 WPF 中获取一个依赖对象的所有依赖项属性 本文介绍如何在 WPF 中获取一个依赖对象的所有依赖项属性. 本文内容 通过 WPF 标记获取 通过设计器专用方法获取 通过 WPF 标记获取 p ...
- 遍历js对象中的属性
可以使用js自带的for in.也可以使用Ext JS中的方法来遍历js对象中的属性 代码如下: /** 遍历对象 */ var person = {name:'张泰松',age:28}; //js方 ...
- 深入理解JavaScript中的属性和特性
深入理解JavaScript中的属性和特性 JavaScript中属性和特性是完全不同的两个概念,这里我将根据自己所学,来深入理解JavaScript中的属性和特性. 主要内容如下: 理解JavaSc ...
随机推荐
- 【原创】Git 分支的合并【Learn Git Branching】
merge git merge是我们要学习的合并工作的第一个方法.合并产生一个特殊的提交记录,它包含两个唯一父提交.有两个父提交的提交记录本质上是:“我想把这两个父提交本身及它们的父提交集 ...
- 痞子衡嵌入式:备受开源社区推崇的分布式版本控制工具(Git)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是分布式版本控制工具Git. 1.为什么需要版本控制系统? 单人软件项目开发过程,往往很多功能都是逐步增加的,在代码开发过程中,有的时候功 ...
- ARM 汇编指令 DCD
简介 DCD:数据定义( Data Definition )伪指令 一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化. 语法格式: 标号 DCD(或 DCDU) 表达式 DCD(或 ...
- SpringBoot系列——EnableScheduling,对定时器的支持
前言 定时器功能在项目里面往往会用到,比如定时发送邮件.定时释放数据库资源:这里记录一下springboot对定时器的支持的简单实例 cron表达式 开始之前要先介绍一下cron表达式,这里当一下百度 ...
- MyBatis学习总结(一)——ORM概要与MyBatis快速起步
程序员应该将核心关注点放在业务上,而不应该将时间过多的浪费在CRUD中,多数的ORM框架都把增加.修改与删除做得非常不错了,然后数据库中查询无疑是使用频次最高.复杂度大.与性能密切相关的操作,我们希望 ...
- ___简单的MVC单个图片上传预览
js: $("#btnImg").click(function () { $("#form0").ajaxSubmit({ url: "/Studen ...
- c# 调用微吼直播API
/// <summary> /// 调用微吼直播API /// </summary> /// <param name="appKey">< ...
- input type=file 上传文件样式美化(转载)
input type=file 上传文件样式美化 来源:https://www.jianshu.com/p/6390595e5a36 在做input文本上传时,由于html原生的上传按钮比较丑,需要对 ...
- adb命令笔记
adb devices [-l]: 列出所有连接设备 l: 列出设备限定符 adb connect <host>[:<port>]: 通过ip连接到设备 host: IP po ...
- 使用mybatis开发dao问题总结
代码片段: @Override public User getUserById(Integer id) { SqlSession sqlSession = sqlSessionFactory.open ...