C# 比较类型对象的类属性

C# 比较类型对象的类属性,c#,C#,我试图记录对象的每个属性在更新后的历史记录,只有当它发生更改时。我没有对每个属性执行if语句,而是决定循环遍历每个属性,在这些属性中我定义了一个自定义属性,以筛选出我不想记录的属性,然后比较新旧值以查看它们是否已更改 然而,检查每个obj实例的相等性似乎很大,而且非常具体,因为我还有枚举类型要比较。有没有更好的方法来实现这一点或重构我的代码 代码示例 MyClass public class MyClassDto { [Comparible] public MyC

我试图记录对象的每个属性在更新后的历史记录,只有当它发生更改时。我没有对每个属性执行if语句,而是决定循环遍历每个属性,在这些属性中我定义了一个自定义属性,以筛选出我不想记录的属性,然后比较新旧值以查看它们是否已更改

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

代码示例

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;
    }
对象比较功能

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;
    }

基本类型实际上不需要单独的案例。对于自定义类型,应该让它们重写,以便将相等性测试逻辑封装在类中

这样,您的
IsEqual
函数应该只是调用:

object.Equals
的注释中:

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

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

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

如果这两个对象不代表相同的对象引用,并且都不为null,那么它将调用objA.Equals(objB)并返回结果。这意味着如果objA重写Object.Equals(Object)方法,则调用此重写


非常感谢。完全忽略了object.equals方法。我假设当涉及枚举时,它仍然会正确地调用objA.Equals(objB)来计算它的实际值,或者枚举是否需要覆盖对象。Equals?@Kaustix是的,枚举类型有自己的Equals覆盖:谢谢!请吃一块饼干!