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 - 在两个点之间平滑地缩放平移.请 ...
随机推荐
- Hadoop入门进阶课程4--HDFS原理及操作
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博主为石山园,博客地址为 http://www.cnblogs.com/shishanyuan ...
- iOS-给UIView添加点击事件
一.当遇到一些UIView 或者 UIView的子类时,比如点击UIImageView要放大图片等. 二.步骤: 1.首先要确保打开控件的用户交互,userInteractionEnabled设置成Y ...
- 我也想聊聊 OAuth 2.0 —— Access Token
这是一篇待在草稿箱半年之久的文章 连我自己都不知道我的草稿箱有多少未发布的文章了.这应该是我在上一家公司未解散之前写的,记得当时是要做一个开发者中心,很不幸. 今天,打开草稿箱有种莫名的伤感,看到这个 ...
- 操作ACCESS数据库注意事项
以下问题都是容易忽略,但却不容易找出问题的所在,让我头疼不少,故在此列出,即是一个总结,同样也给其他人参与! 1.使用参数形式执行SQL命令时,参数数组需与在SQL语句中参数名出现的位置及名称必须完全 ...
- IOS开发UI基础之UIScrollView
什么是UIScrollView ● 移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ● 当展⽰示的内容较多,超出⼀一个屏幕时,⽤用户可通过滚动⼿手势来查看屏幕以外的内容 ...
- Python+Selenium进行UI自动化测试项目中,常用的小技巧4:日志打印,longging模块(控制台和文件同时输出)
在前段时间,为了给项目中加入日志功能,就想到了 logging 模块,百度logging一大推,都是各种复制的,并没有找到自己想要的结果:我的目的很简单,就是:在把日志写入文件的同时在控制台输出,更加 ...
- Linux内核分析课程笔记(一)
linux内核分析课程笔记(一) 冯诺依曼体系结构 冯诺依曼体系结构实际上就是存储程序计算机. 从两个层面来讲: 从硬件的角度来看,冯诺依曼体系结构逻辑上可以抽象成CPU和内存,通过总线相连.CPU上 ...
- 在SQL存储过程中给条件变量加上单引号
在SQL存储过程中给条件变量加上单引号,不加语句就会出问题,以下就是在存储过程中将条件where设置成了动态变化的,给where赋完值再和前面的语句拼接,再execute(SQL) ), )), )+ ...
- 字典树(Trie树)实现与应用
一.概述 1.基本概念 字典树,又称为单词查找树,Tire数,是一种树形结构,它是一种哈希树的变种. 2.基本性质 根节点不包含字符,除根节点外的每一个子节点都包含一个字符 从根节点到某一节点.路径上 ...
- 媒体对象 - Media Objects(摘录)
原文链接:http://www.jianshu.com/p/6443be21efbd 一个媒体对象由以下及部分组成 父容器 .media 媒体部分 .media-left 或者 .media-righ ...