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 rabbit = new ProductSubitem() { ID = Guid.NewGuid(), Name = "米兔", Detail = new Detail() { ID = Guid.NewGuid(), Introduce = "小米米兔", Price = 10 } }; var subitem1 = new ProductSubitem() { ID = earphoneID, Name = "耳机", Detail = new Detail() { ID = Guid.NewGuid(), Introduce = "小米耳机", Price = 79 } }; var subitem11 = new ProductSubitem() { ID = earphoneID, Name = "耳机", Detail = new Detail() { ID = Guid.NewGuid(), Introduce = "小米耳机", Price = 89 } }; var subitem2 = new ProductSubitem() { ID = Guid.NewGuid(), Name = "手机贴膜", Detail = new Detail() { ID = Guid.NewGuid(), Introduce = "小米手机贴膜", Price = 5 } }; // 构建产品原始数据 var beijing = new Province { ID = Guid.NewGuid(), Name = "北京" }; var mifan1 = new User() { ID = Guid.NewGuid(), UserName = "mifan1", RealName = "北京米粉" }; var attachmentFiles = new List<AttachmentFile>() { new AttachmentFile(){ID = Guid.NewGuid(),Name = "说明书",SavePath = @"/xiaomi/document/note.doc",Size = 20} }; var id = Guid.NewGuid(); var detailID = Guid.NewGuid(); var product = new Product() { ID = id, Name = "小米Note", Detail = new Detail() { ID = detailID, Introduce = "小米新款手机", Price = 2299 }, 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 = new Detail() { ID = detailID, Introduce = "小米新款手机", Price = 3399 }, // 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" };
多层级实体:
1 /// <summary> 2 /// 产品 3 /// </summary> 4 public class Product 5 { 6 public Guid ID { get; set; } 7 8 /// <summary> 9 /// 名称 10 /// </summary> 11 public string Name { get; set; } 12 13 /// <summary> 14 /// 详情 15 /// </summary> 16 public Detail Detail { get; set; } 17 18 /// <summary> 19 /// 产地 20 /// </summary> 21 public Province Province { get; set; } 22 23 /// <summary> 24 /// 创建用户 25 /// </summary> 26 public User CreateUser { get; set; } 27 28 public DateTime CreateTime { get; set; } 29 30 /// <summary> 31 /// 产品子项 32 /// </summary> 33 public List<ProductSubitem> ProductSubitems { get; set; } 34 35 /// <summary> 36 /// 相关文件 37 /// </summary> 38 public List<AttachmentFile> AttachmentFiles { get; set; } 39 } 40 41 /// <summary> 42 /// 用户 43 /// </summary> 44 public class User 45 { 46 public Guid ID { get; set; } 47 48 public string UserName { get; set; } 49 50 public string RealName { get; set; } 51 } 52 53 /// <summary> 54 /// 省份 55 /// </summary> 56 public class Province 57 { 58 public Guid ID { get; set; } 59 60 public string Name { get; set; } 61 } 62 63 /// <summary> 64 /// 介绍 65 /// </summary> 66 public class Detail 67 { 68 public Guid ID { get; set; } 69 70 /// <summary> 71 /// 介绍 72 /// </summary> 73 public string Introduce { get; set; } 74 75 /// <summary> 76 /// 价格 77 /// </summary> 78 public double Price { get; set; } 79 } 80 81 public class ProductSubitem 82 { 83 public Guid ID { get; set; } 84 85 public string Name { get; set; } 86 87 /// <summary> 88 /// 详情 89 /// </summary> 90 public Detail Detail { get; set; } 91 } 92 93 /// <summary> 94 /// 文件(图片、文档) 95 /// </summary> 96 public class AttachmentFile 97 { 98 public Guid ID { get; set; } 99 100 public string Name { get; set; } 101 102 public double Size { get; set; } 103 104 public string SavePath { get; set; } 105 }
多层级实体
最终匹配结果:
ComparisonField 完整方法:
1 namespace ComparisonFieldTest 2 { 3 public class Common 4 { 5 /// <summary> 6 /// 比较字段 7 /// </summary> 8 /// <param name="beforeUpdateData">原来的值</param> 9 /// <param name="afterUpdateData">页面提交的新值</param> 10 /// <param name="specialFields">特殊处理字段</param> 11 /// <param name="ignoreFields">忽略处理字段</param> 12 /// <returns></returns> 13 public static 14 List<FieldItem> ComparisonField(Object beforeUpdateData, Object afterUpdateData, List<string> specialFields, List<string> ignoreFields) 15 { 16 var fieldItems = new List<FieldItem>(); 17 if (null == afterUpdateData || null == beforeUpdateData) 18 return fieldItems; 19 20 Type type = afterUpdateData.GetType(); 21 var fields = type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); 22 foreach (var field in fields) 23 { 24 // 忽略字段不处理 25 if (ignoreFields.Contains(field.Name)) 26 { 27 continue; 28 } 29 30 // 取得字段的值 31 object afterUpdateItem = field.GetValue(afterUpdateData); 32 var beforeUpdateItem = beforeUpdateData.GetType().GetProperty(field.Name).GetValue(beforeUpdateData, null); 33 34 // 都为空不比较 35 if (afterUpdateItem == null && beforeUpdateItem == null) 36 { 37 continue; 38 } 39 40 if (field.PropertyType.IsValueType || field.PropertyType.Name.StartsWith("String")) 41 { 42 // String类型处理 43 44 // 直接比较是否相等,若不相等直接记录 45 if (afterUpdateItem.ToString() != beforeUpdateItem.ToString()) 46 { 47 fieldItems.Add(new FieldItem 48 { 49 ChangeField = field.Name, 50 BeforeChangeContent = beforeUpdateItem.ToString(), 51 AfterChangeContent = afterUpdateItem.ToString(), 52 Description = "修改" 53 }); 54 } 55 } 56 else if (field.PropertyType.IsGenericType) 57 { 58 // List类型处理 59 60 var afterUpdateList = field.GetValue(afterUpdateData, null); 61 var beforeUpdateList = beforeUpdateData.GetType().GetProperty(field.Name).GetValue(beforeUpdateData, null); 62 63 /* 64 * 判断两个对象是否一致,若一致说明未修改,若不一致说明有修改 65 * 修改有三种情况:新增,修改,删除,通过两次遍历找出 66 */ 67 68 var afterList = afterUpdateList as IEnumerable<object>; 69 var beforeList = beforeUpdateList as IEnumerable<object>; 70 71 // 1.遍历新的与原数据比较 72 foreach (var afterObj in afterList) 73 { 74 Type tp = afterObj.GetType(); 75 var property = tp.Name; 76 77 var ID = afterObj.GetType().GetProperty("ID").GetValue(afterObj); 78 if (ID == null) 79 { 80 // 1. 新录入项 81 82 if (specialFields.Contains(field.Name)) 83 { 84 // 新增,特殊处理字段 85 fieldItems.Add(new FieldItem 86 { 87 ChangeField = property, 88 BeforeChangeContent = string.Empty, 89 AfterChangeContent = ID.ToString(), 90 Description = "新增" 91 }); 92 } 93 else 94 { 95 var properties = afterObj.GetType().GetProperties(); 96 var afterChangeContent = new StringBuilder(); 97 foreach (var propertyInfo in properties) 98 { 99 var propertyName = propertyInfo.Name; 100 var value = propertyInfo.GetValue(afterObj); 101 afterChangeContent.Append(propertyName + ":" + value + "; "); 102 } 103 var afterChangeContentStr = afterChangeContent.ToString().Substring(0, afterChangeContent.ToString().Length - 1); 104 105 fieldItems.Add(new FieldItem 106 { 107 ChangeField = property, 108 BeforeChangeContent = string.Empty, 109 AfterChangeContent = afterChangeContentStr, 110 Description = "新增" 111 }); 112 } 113 } 114 else 115 { 116 // 2.修改项 117 118 if (!specialFields.Contains(field.Name)) 119 { 120 var beforeObj = beforeList.FirstOrDefault(b => b.GetType().GetProperty("ID").GetValue(b).ToString() == ID.ToString()); 121 if (beforeObj != null) 122 { 123 // 1.判断两个对象是否一致,若一致不管,若不一致再处理 124 125 // 递归调用 126 var result = ComparisonField(beforeObj, afterObj, specialFields, ignoreFields); 127 if (result.Any()) 128 { 129 // 修改操作 130 fieldItems.Add(new FieldItem 131 { 132 ChangeField = property, 133 BeforeChangeContent = string.Join(";", result.Select(t => t.ChangeField + ":" + t.BeforeChangeContent)), 134 AfterChangeContent = string.Join(";", result.Select(t => t.ChangeField + ":" + t.AfterChangeContent)), 135 Description = "修改" 136 }); 137 } 138 } 139 else 140 { 141 var properties = afterObj.GetType().GetProperties(); 142 var afterChangeContent = new StringBuilder(); 143 foreach (var propertyInfo in properties) 144 { 145 var propertyName = propertyInfo.Name; 146 var value = propertyInfo.GetValue(afterObj); 147 afterChangeContent.Append(propertyName + ":" + value + "; "); 148 } 149 var afterChangeContentStr = afterChangeContent.ToString().Substring(0, afterChangeContent.ToString().Length - 1); 150 151 fieldItems.Add(new FieldItem 152 { 153 ChangeField = property, 154 BeforeChangeContent = string.Empty, 155 AfterChangeContent = afterChangeContentStr, 156 Description = "新增" 157 }); 158 } 159 } 160 } 161 } 162 163 // 2.遍历原数据与新的比较 164 foreach (var beforeObj in beforeList) 165 { 166 var ID = beforeObj.GetType().GetProperty("ID").GetValue(beforeObj); 167 var afterObj = afterList.FirstOrDefault(b => b.GetType().GetProperty("ID").GetValue(b).ToString() == ID.ToString()); 168 if (afterObj == null) 169 { 170 // 删除操作 171 172 if (specialFields.Contains(field.Name)) 173 { 174 // 删除,特殊处理字段 175 fieldItems.Add(new FieldItem 176 { 177 ChangeField = beforeObj.GetType().Name, 178 BeforeChangeContent = ID.ToString(), 179 AfterChangeContent = string.Empty, 180 Description = "删除" 181 }); 182 } 183 else 184 { 185 var properties = beforeObj.GetType().GetProperties(); 186 var beforeContent = new StringBuilder(); 187 foreach (var propertyInfo in properties) 188 { 189 var propertyName = propertyInfo.Name; 190 var value = propertyInfo.GetValue(beforeObj); 191 beforeContent.Append(propertyName + ":" + value + "; "); 192 } 193 var beforeContentStr = beforeContent.ToString() 194 .Substring(0, beforeContent.ToString().Length - 1); 195 196 fieldItems.Add(new FieldItem 197 { 198 ChangeField = beforeObj.GetType().Name, 199 BeforeChangeContent = beforeContentStr, 200 AfterChangeContent = string.Empty, 201 Description = "删除" 202 }); 203 } 204 } 205 } 206 } 207 else if (specialFields.Contains(field.Name)) 208 { 209 // 特殊字段处理 210 if (afterUpdateItem != null && beforeUpdateItem == null) 211 { 212 // 第一种情况:新增 213 fieldItems.Add(new FieldItem 214 { 215 ChangeField = field.Name, 216 BeforeChangeContent = string.Empty, 217 AfterChangeContent = afterUpdateItem.GetType().GetProperty("ID").GetValue(afterUpdateItem, null).ToString(), 218 Description = "新增" 219 }); 220 } 221 else if (afterUpdateItem == null && beforeUpdateItem != null) 222 { 223 // 第二种情况:删除 224 fieldItems.Add(new FieldItem 225 { 226 ChangeField = field.Name, 227 BeforeChangeContent = beforeUpdateItem.GetType().GetProperty("ID").GetValue(beforeUpdateItem, null).ToString(), 228 AfterChangeContent = string.Empty, 229 Description = "删除" 230 }); 231 } 232 else 233 { 234 // 第一种情况:修改 235 var afterId = afterUpdateItem.GetType().GetProperty("ID").GetValue(afterUpdateItem, null); 236 var beforeId = beforeUpdateItem.GetType().GetProperty("ID").GetValue(beforeUpdateItem, null); 237 if (!afterId.Equals(beforeId)) 238 { 239 fieldItems.Add(new FieldItem 240 { 241 ChangeField = field.Name, 242 BeforeChangeContent = beforeId.ToString(), 243 AfterChangeContent = afterId.ToString(), 244 Description = "修改" 245 }); 246 } 247 } 248 } 249 else 250 { 251 // 递归调用 252 var result = ComparisonField(beforeUpdateItem, afterUpdateItem, specialFields, ignoreFields); 253 fieldItems.AddRange(result); 254 } 255 } 256 return fieldItems; 257 } 258 } 259 260 /// <summary> 261 /// 建设项目变更字段记录 262 /// </summary> 263 public class FieldItem 264 { 265 /// <summary> 266 /// 变更字段 267 /// </summary> 268 public string ChangeField { get; set; } 269 270 /// <summary> 271 /// 修改前内容(针对建设图时,存储建设图ID) 272 /// </summary> 273 public string BeforeChangeContent { get; set; } 274 275 /// <summary> 276 /// 修改后内容(针对建设图时,存储建设图ID) 277 /// </summary> 278 public string AfterChangeContent { get; set; } 279 280 /// <summary> 281 /// 描述 282 /// </summary> 283 public string Description { get; set; } 284 } 285 }
Common.ComparisonField 完整方法
示例代码下载:
时间: 2024-10-26 04:12:14