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,以下是修改項:
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 完整方法
示例代碼下載:
ComparisonFieldTest.zip