C# 两个Object比较
C#两个Object进行比较,Object里只是简单属性,不存在层级关系还比较好处理,如果遇到多层级的就有点麻烦。
1、简单Object比较
/// <summary> /// 比较字段 /// </summary> /// <param name="beforeUpdateData">原来的值</param> /// <param name="afterUpdateData">页面提交的新值</param> /// <param name="specialFields">特殊处理字段</param> /// <param name="ignoreFields">忽略处理字段</param> /// <returns></returns> public static List<FieldItem> ComparisonField(Object beforeUpdateData,Object afterUpdateData,List<string> specialFields,List<string> ignoreFields) { var fieldItems = new List<FieldItem>(); if (null == afterUpdateData || null == beforeUpdateData) return fieldItems; Type type = afterUpdateData.GetType(); var fields = type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); foreach (var field in fields) {// 取得字段的值 object afterUpdateItem = field.GetValue(afterUpdateData); var beforeUpdateItem = beforeUpdateData.GetType().GetProperty(field.Name).GetValue(beforeUpdateData, null); if (field.PropertyType.IsValueType || field.PropertyType.Name.StartsWith("String")) { // String类型处理 // 直接比较是否相等,若不相等直接记录 if (afterUpdateItem.ToString() != beforeUpdateItem.ToString()) { fieldItems.Add(new FieldItem { ChangeField = field.Name, BeforeChangeContent = beforeUpdateItem.ToString(), AfterChangeContent = afterUpdateItem.ToString(), Description = "修改" }); } } } return fieldItems; }
2、复杂Object比较
对比 product 与 newProduct 两个Object,以下是修改项:
- 修改Name:小米Note -> 小米Note2
- 修改Detail中的Price:2299 -> 3399
- 修改耳机价格:79 -> 89
- 产品子项新增了米兔
class Program { static void Main(string[] args) { var earphoneID = Guid.NewGuid(); } }; } }; } }; } }; // 构建产品原始数据 var beijing = new Province { ID = Guid.NewGuid(), Name = "北京" }; var mifan1 = new User() { ID = Guid.NewGuid(), UserName = "mifan1", RealName = "北京米粉" }; var attachmentFiles = new List<AttachmentFile>() { } }; var id = Guid.NewGuid(); var detailID = Guid.NewGuid(); var product = new Product() { ID = id, Name = "小米Note", Detail = }, Province = beijing, CreateUser = mifan1, CreateTime = DateTime.Now, ProductSubitems = new List<ProductSubitem>() { subitem1, subitem2 }, AttachmentFiles = attachmentFiles }; var newProduct = new Product() { ID = id, Name = "小米Note2", // 1.修改了Name:小米Note -> 小米Note2 Detail = }, // 2.修改了Detail中的Price:2299 -> 3399 Province = beijing, CreateUser = mifan1, CreateTime = DateTime.Now, ProductSubitems = new List<ProductSubitem>() { rabbit, subitem11, subitem2 }, // 3.修改耳机价格:79 -> 89 | 4.产品子项新增了米兔。 AttachmentFiles = attachmentFiles }; var comparisonFieldList = Common.ComparisonField(product, newProduct, SpecialFields, IgnoreFields); foreach (var fieldItem in comparisonFieldList) { Console.WriteLine(string.Format("变更字段:{0}, 修改前内容:{1}, 修改后内容:{2}, 描述:{3}", fieldItem.ChangeField, fieldItem.BeforeChangeContent, fieldItem.AfterChangeContent,fieldItem.Description)); } Console.ReadLine(); } /// <summary> /// 特殊字段,只做ID比较 /// </summary> public static readonly List<string> SpecialFields = new List<string>() { "Province","AttachmentFiles" }; /// <summary> /// 忽略字段 /// </summary> public static readonly List<string> IgnoreFields = new List<string>() { "ID", "CreateTime", "CreateUser" };
多层级实体:
/// <summary> /// 产品 /// </summary> public class Product { public Guid ID { get; set; } /// <summary> /// 名称 /// </summary> public string Name { get; set; } /// <summary> /// 详情 /// </summary> public Detail Detail { get; set; } /// <summary> /// 产地 /// </summary> public Province Province { get; set; } /// <summary> /// 创建用户 /// </summary> public User CreateUser { get; set; } public DateTime CreateTime { get; set; } /// <summary> /// 产品子项 /// </summary> public List<ProductSubitem> ProductSubitems { get; set; } /// <summary> /// 相关文件 /// </summary> public List<AttachmentFile> AttachmentFiles { get; set; } } /// <summary> /// 用户 /// </summary> public class User { public Guid ID { get; set; } public string UserName { get; set; } public string RealName { get; set; } } /// <summary> /// 省份 /// </summary> public class Province { public Guid ID { get; set; } public string Name { get; set; } } /// <summary> /// 介绍 /// </summary> public class Detail { public Guid ID { get; set; } /// <summary> /// 介绍 /// </summary> public string Introduce { get; set; } /// <summary> /// 价格 /// </summary> public double Price { get; set; } } public class ProductSubitem { public Guid ID { get; set; } public string Name { get; set; } /// <summary> /// 详情 /// </summary> public Detail Detail { get; set; } } /// <summary> /// 文件(图片、文档) /// </summary> public class AttachmentFile { public Guid ID { get; set; } public string Name { get; set; } public double Size { get; set; } public string SavePath { get; set; } }
多层级实体
最终匹配结果:
ComparisonField 完整方法:
namespace ComparisonFieldTest { public class Common { /// <summary> /// 比较字段 /// </summary> /// <param name="beforeUpdateData">原来的值</param> /// <param name="afterUpdateData">页面提交的新值</param> /// <param name="specialFields">特殊处理字段</param> /// <param name="ignoreFields">忽略处理字段</param> /// <returns></returns> public static List<FieldItem> ComparisonField(Object beforeUpdateData, Object afterUpdateData, List<string> specialFields, List<string> ignoreFields) { var fieldItems = new List<FieldItem>(); if (null == afterUpdateData || null == beforeUpdateData) return fieldItems; Type type = afterUpdateData.GetType(); var fields = type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); foreach (var field in fields) { // 忽略字段不处理 if (ignoreFields.Contains(field.Name)) { continue; } // 取得字段的值 object afterUpdateItem = field.GetValue(afterUpdateData); var beforeUpdateItem = beforeUpdateData.GetType().GetProperty(field.Name).GetValue(beforeUpdateData, null); // 都为空不比较 if (afterUpdateItem == null && beforeUpdateItem == null) { continue; } if (field.PropertyType.IsValueType || field.PropertyType.Name.StartsWith("String")) { // String类型处理 // 直接比较是否相等,若不相等直接记录 if (afterUpdateItem.ToString() != beforeUpdateItem.ToString()) { fieldItems.Add(new FieldItem { ChangeField = field.Name, BeforeChangeContent = beforeUpdateItem.ToString(), AfterChangeContent = afterUpdateItem.ToString(), Description = "修改" }); } } else if (field.PropertyType.IsGenericType) { // List类型处理 var afterUpdateList = field.GetValue(afterUpdateData, null); var beforeUpdateList = beforeUpdateData.GetType().GetProperty(field.Name).GetValue(beforeUpdateData, null); /* * 判断两个对象是否一致,若一致说明未修改,若不一致说明有修改 * 修改有三种情况:新增,修改,删除,通过两次遍历找出 */ var afterList = afterUpdateList as IEnumerable<object>; var beforeList = beforeUpdateList as IEnumerable<object>; // 1.遍历新的与原数据比较 foreach (var afterObj in afterList) { Type tp = afterObj.GetType(); var property = tp.Name; var ID = afterObj.GetType().GetProperty("ID").GetValue(afterObj); if (ID == null) { // 1. 新录入项 if (specialFields.Contains(field.Name)) { // 新增,特殊处理字段 fieldItems.Add(new FieldItem { ChangeField = property, BeforeChangeContent = string.Empty, AfterChangeContent = ID.ToString(), Description = "新增" }); } else { var properties = afterObj.GetType().GetProperties(); var afterChangeContent = new StringBuilder(); foreach (var propertyInfo in properties) { var propertyName = propertyInfo.Name; var value = propertyInfo.GetValue(afterObj); afterChangeContent.Append(propertyName + ":" + value + "; "); } , afterChangeContent.ToString().Length - ); fieldItems.Add(new FieldItem { ChangeField = property, BeforeChangeContent = string.Empty, AfterChangeContent = afterChangeContentStr, Description = "新增" }); } } else { // 2.修改项 if (!specialFields.Contains(field.Name)) { var beforeObj = beforeList.FirstOrDefault(b => b.GetType().GetProperty("ID").GetValue(b).ToString() == ID.ToString()); if (beforeObj != null) { // 1.判断两个对象是否一致,若一致不管,若不一致再处理 // 递归调用 var result = ComparisonField(beforeObj, afterObj, specialFields, ignoreFields); if (result.Any()) { // 修改操作 fieldItems.Add(new FieldItem { ChangeField = property, BeforeChangeContent = string.Join(";", result.Select(t => t.ChangeField + ":" + t.BeforeChangeContent)), AfterChangeContent = string.Join(";", result.Select(t => t.ChangeField + ":" + t.AfterChangeContent)), Description = "修改" }); } } else { var properties = afterObj.GetType().GetProperties(); var afterChangeContent = new StringBuilder(); foreach (var propertyInfo in properties) { var propertyName = propertyInfo.Name; var value = propertyInfo.GetValue(afterObj); afterChangeContent.Append(propertyName + ":" + value + "; "); } , afterChangeContent.ToString().Length - ); fieldItems.Add(new FieldItem { ChangeField = property, BeforeChangeContent = string.Empty, AfterChangeContent = afterChangeContentStr, Description = "新增" }); } } } } // 2.遍历原数据与新的比较 foreach (var beforeObj in beforeList) { var ID = beforeObj.GetType().GetProperty("ID").GetValue(beforeObj); var afterObj = afterList.FirstOrDefault(b => b.GetType().GetProperty("ID").GetValue(b).ToString() == ID.ToString()); if (afterObj == null) { // 删除操作 if (specialFields.Contains(field.Name)) { // 删除,特殊处理字段 fieldItems.Add(new FieldItem { ChangeField = beforeObj.GetType().Name, BeforeChangeContent = ID.ToString(), AfterChangeContent = string.Empty, Description = "删除" }); } else { var properties = beforeObj.GetType().GetProperties(); var beforeContent = new StringBuilder(); foreach (var propertyInfo in properties) { var propertyName = propertyInfo.Name; var value = propertyInfo.GetValue(beforeObj); beforeContent.Append(propertyName + ":" + value + "; "); } var beforeContentStr = beforeContent.ToString() .Substring(, beforeContent.ToString().Length - ); fieldItems.Add(new FieldItem { ChangeField = beforeObj.GetType().Name, BeforeChangeContent = beforeContentStr, AfterChangeContent = string.Empty, Description = "删除" }); } } } } else if (specialFields.Contains(field.Name)) { // 特殊字段处理 if (afterUpdateItem != null && beforeUpdateItem == null) { // 第一种情况:新增 fieldItems.Add(new FieldItem { ChangeField = field.Name, BeforeChangeContent = string.Empty, AfterChangeContent = afterUpdateItem.GetType().GetProperty("ID").GetValue(afterUpdateItem, null).ToString(), Description = "新增" }); } else if (afterUpdateItem == null && beforeUpdateItem != null) { // 第二种情况:删除 fieldItems.Add(new FieldItem { ChangeField = field.Name, BeforeChangeContent = beforeUpdateItem.GetType().GetProperty("ID").GetValue(beforeUpdateItem, null).ToString(), AfterChangeContent = string.Empty, Description = "删除" }); } else { // 第一种情况:修改 var afterId = afterUpdateItem.GetType().GetProperty("ID").GetValue(afterUpdateItem, null); var beforeId = beforeUpdateItem.GetType().GetProperty("ID").GetValue(beforeUpdateItem, null); if (!afterId.Equals(beforeId)) { fieldItems.Add(new FieldItem { ChangeField = field.Name, BeforeChangeContent = beforeId.ToString(), AfterChangeContent = afterId.ToString(), Description = "修改" }); } } } else { // 递归调用 var result = ComparisonField(beforeUpdateItem, afterUpdateItem, specialFields, ignoreFields); fieldItems.AddRange(result); } } return fieldItems; } } /// <summary> /// 建设项目变更字段记录 /// </summary> public class FieldItem { /// <summary> /// 变更字段 /// </summary> public string ChangeField { get; set; } /// <summary> /// 修改前内容(针对建设图时,存储建设图ID) /// </summary> public string BeforeChangeContent { get; set; } /// <summary> /// 修改后内容(针对建设图时,存储建设图ID) /// </summary> public string AfterChangeContent { get; set; } /// <summary> /// 描述 /// </summary> public string Description { get; set; } } }
Common.ComparisonField 完整方法
示例代码下载:
C# 两个Object比较的更多相关文章
- JS学习之--比较两个Object数组是否相等
一.问题 在js中是不能直接用“==”或者“===”来计算两个数组是否相等的,那么就需要对数组的值进行比较: 二.次解决方案 对于比较两个数组次要的方法有如下几种,为什么说是次要解决方案呢?因为它不能 ...
- 把两个object对象合并成一个对象 属性名称相同的变为后面对象的值
object.assign(from,obj)------object.assign(目标对象,被合并的对象)
- 如何在Node.js中合并两个复杂对象
通常情况下,在Node.js中我们可以通过underscore的extend或者lodash的merge来合并两个对象,但是对于像下面这种复杂的对象,要如何来应对呢? 例如我有以下两个object: ...
- 在Salesforce中为Object创建Master-Detail(Child-Relationship)关联关系
在Salesforce中可以将两个Object建立起一对多的关联关系,本篇文章就简单的叙述一下将两个Object(EricSunObj & EricSunObjC)设置成Master-Deta ...
- 关于C++中Object所占内存空间探索1
关于C++中Object所占内存空间探索(一) 有如下问题: 1. 一个空类, class X{ }; 2.类中含有数据成员(Data Member), class X { public: //Fun ...
- Object类型转换成自定义类型(向下转型)
Object类型转换成自定义类型 场景: 从数据库或者别的途径接收对象的时候用Object,但是用的时候怎么object点(方法提示 | alt+'/'),都点不出自定义类型的方法. 比如,数据库查询 ...
- salesforce 零基础学习(六十三)Comparable实现Object列表数据的自定义排序
项目中通常有些需求为需要将某个sObject的数据列表按照某种规则排序显示到前台页面上,但是list上面的sort远远满足不了复杂的功能,此种情况需要自定义比较两个object大小的方法,所以需要创建 ...
- JDK核心JAVA源代码解析(1) - Object
想写这个系列非常久了,对自己也是个总结与提高.原来在学JAVA时.那些JAVA入门书籍会告诉你一些规律还有法则,可是用的时候我们一般非常难想起来,由于我们用的少而且不知道为什么.知其所以然方能印象深刻 ...
- 软件项目技术点(1)——d3.interpolateZoom-在两个点之间平滑地缩放平移
AxeSlide软件项目梳理 canvas绘图系列知识点整理 软件参考d3的知识点 我们在软件中主要用到d3.js的核心函数d3.interpolateZoom - 在两个点之间平滑地缩放平移.请 ...
随机推荐
- CentOS 7.2 MySQL 5.7 主从配置
MySQL的安装:CentOS 7.2 yum方式安装MySQL 5.7 两台服务器分别如下: Master:192.168.1.100 Slave:192.168.1.101 Master配置: 编 ...
- 探索jdk8之ConcurrentHashMap 的实现机制
在介绍ConcurrentHashMap源码之前,很有必要复习下java并发编程中的一些基础知识,比如内存模型等. 存储模型 并发编程中的三个概念 1.原子性 2.可见性 3.重排序 对HashMap ...
- VM不能连入局域网
如果选了Host-only,那么虚拟机与跑虚拟机的宿主就无法连通了. 可以选用Bridged模式,那么虚拟机与跑虚拟机的主机连通了
- Android程序ToDoList
本文的目的是创建一个简单的ToDoList列表. 这个应用的功能是记录我的代办事项,简单到不需要本地存储,所有的代办事项都只是存储在内存中,就是只有程序打开的时候可以增加查看代办事项,当程序关闭的时候 ...
- Scrum项目1.0
1) N (Need 需求) 面向小学生 2) A (Approach 做法) 3) B (Benefit 好处) 让小学生以游戏的方式进行学习 4) C (Competitors 竞争) 减少练习 ...
- 准备.Net转前端开发-WPF界面框架那些事,搭建基础框架
题外话 最近都没怎么写博客,主要是最近在看WPF方面的书<wpf-4-unleashed.pdf>,挑了比较重要的几个章节学习了下WPF基础技术.另外,也把这本书推荐给目前正在从事WPF开 ...
- 重构第9天:提取接口(Extract Interface)
理解:提取接口的意思是,多于一个类共同使用某个类中的方法或属性,那么我们可以把这些方法和属性提出来,作为一个单独的接口.这样的好处是解除代码间的依赖,降低耦合性. 详解: 先看重构前的代码: publ ...
- .NET程序的编译和运行
程序的编译和运行,总得来说大体是:首先写好的程序是源代码,然后编译器编译为本地机器语言,最后在本地操作系统运行. 下图为传统代码编译运行过程: .NET的编译和运行过程与之类似,首先编写好的源代码,然 ...
- sql server2008中sql server身份能登录,window身份登录不了
用sql server身份的sa登录成功进入,一切正常,用window身份登录不了,问题如下
- 小白学Linux(四)--系统常用命令
这里记录一下基础的系统常用命令,都是日常可能用到的,需要记住的一些命令.主要分为5个模块:关于时间,输出/查看,关机/重启,压缩归档和查找. 时间: date :查看设置当前系统时间,dat ...