比较Object类型的类属性

本文关键字:属性 类型 Object 比较 | 更新日期: 2023-09-27 18:14:36

我试图记录一个对象的每个属性的历史记录,只有在它已经改变的情况下才更新。而不是为每个属性做一个if语句,我决定循环通过每个属性,我已经定义了一个自定义属性来过滤掉那些我不想记录的,然后比较旧的和新的值,看看他们是否已经改变。

然而,检查每个对象的相等性似乎很大,而且非常具体,因为我也有枚举类型来比较。是否有更好的方法来实现这一点或重构我的代码?

代码范例

MyClass

public class MyClassDto
{
        [Comparible]
        public MyCustomType CustomType{ get; set; }
        [Comparible]
        public DateTime? SomeDate { get; set; }
        [Comparible]
        public decimal? SomeDecimalValue { get; set; }
        [Comparible]
        public int? SomeIntValue { get; set; }
       // Other Non Custom Attribute Type Properties
}

添加历史帮助函数

public void AddHistory(MyClassDto prevMyObject, MyClassDto newMyObject)
{
      if (prevMyObject== null || newMyObject == null) return;
      foreach (var property in prevMyObject.GetType().GetProperties().Where(prop => Attribute.IsDefined(prop, typeof (ComparibleAttribute))))
      {
          var fieldName = property.Name;
          object prevValue = property.GetValue(prevMyObject, null);
          object newValue = newMyObject.GetType().GetProperty(property.Name).GetValue(newMyObject, null);
           if (!IsEqual(prevValue, newValue))
           {
               //Log the field, prevValue, newValue
           }
       }
  }

对象比较函数

   private static bool IsEqual(object obj1, object obj2)
    {
        if (obj1 == null && obj2 == null || obj1 == obj2) return true;
        if (obj1 == null || obj2 == null) return false;
        var objType = obj1.GetType();
        if (objType == typeof (string))
        {
            return string.Equals(obj1.ToString(), obj2.ToString());
        }
        if (objType == typeof (int?))
        {
            return (Convert.ToInt32(obj1) == Convert.ToInt32(obj2));
        }
        if (objType == typeof (decimal?) || objType == typeof (decimal))
        {
            return (decimal.Round(Convert.ToDecimal(obj1), 2) == decimal.Round(Convert.ToDecimal(obj2), 2));
        }
        if (objType == typeof (DateTime?) || objType == typeof (DateTime))
        {
            return (Convert.ToDateTime(obj1) == Convert.ToDateTime(obj2));
        }
        if (objType == typeof (ContractTrackerType))
        {
            return (((MyCustomType) obj1).Name() == ((MyCustomType ) obj2).Name());
        }
        return false;
    }

比较Object类型的类属性

对于基本类型,实际上不需要单独的大小写。对于您的自定义类型,您应该让它们覆盖object.Equals,以便将相等性测试逻辑封装在类中。

有了这个,你的IsEqual函数应该简单地调用object.Equals:
 private static bool IsEqual(object obj1, object obj2)
 {
     return object.Equals(obj1, obj2);
 }

摘自object.Equals注释:

静态Equals(Object, Object)方法指示objA和objB两个对象是否相等。它还允许您测试值为null的对象是否相等。它比较objA和objB是否相等,如下所示:

确定两个对象是否表示相同的对象引用。如果是,该方法返回true。这个测试相当于调用ReferenceEquals方法。另外,如果objA和objB都为null,该方法返回true。

它决定objA或objB是否为空。如果是,则返回false。

如果两个对象不代表相同的对象引用,并且都不为空,则调用objA.Equals(objB)并返回结果。这意味着如果objA覆盖了Object. equals (Object)方法,就会调用这个覆盖。