當前項目需要記錄變更記錄,即用戶在進行編輯后,將變更操作記錄下來。但是數據沒有發生變化,則不記錄。
代碼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 = 0; 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 = 0; 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一個新對象賦值時,其實是在堆上創建了一個內存地址,指向的仍然是原對象,對它操作原對象也會發生變化。所以只有通過拷貝復制一個新對象)