c#判断两个对象和对象中的属性是否相同(以及记录对象中的哪些字段,和详细的改变情况)

当前项目需要记录变更记录,即用户在进行编辑后,将变更操作记录下来。但是数据没有发生变化,则不记录。

代码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一个新对象赋值时,其实是在堆上创建了一个内存地址,指向的仍然是原对象,对它操作原对象也会发生变化。所以只有通过拷贝复制一个新对象)

原文地址:https://www.cnblogs.com/likui-bookHouse/p/9908045.html