2014-07-24 4 views
2

개체의 각 속성에 대한 기록을 변경 한 후에 만 ​​기록하려고합니다. 각 속성에 대해 if 문을 수행하는 대신 로그에 저장하지 않으려는 사용자 정의 속성을 정의한 각 속성을 반복하기로 결정한 다음 이전 값과 새 값을 비교하여 if 그들은 바뀌었다.개체 유형의 클래스 속성 비교

그러나 같음에 대한 각 obj 케이스를 검사하는 것은 비교할 enum 유형을 가지고 있기 때문에 크고 매우 특수한 것처럼 보입니다. 이 코드 나 리팩터링을 더 잘 수행 할 수있는 방법이 있습니까?

코드 예

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

답변

1

기본 유형에는 별도의 사례가 실제로 필요하지 않습니다. 사용자 지정 형식의 경우 object.Equals을 재정의해야하므로 평등성 테스트 논리가 클래스 내에 캡슐화됩니다. object.Equals의 노트에서

private static bool IsEqual(object obj1, object obj2) 
{ 
    return object.Equals(obj1, obj2); 
} 

:이와

, 당신의 IsEqual 기능은 단순히 object.Equals에 호출해야

정적 같음 (개체, Object) 메소드가 있는지 두 개체를 나타냅니다 , objA와 objB는 동일합니다. 또한 값이 같은 객체를 테스트 할 수 있습니다. 다음과 같이 objA와 objB가 동일한 지 비교합니다.

두 객체가 동일한 객체 참조를 나타내는 지 여부를 결정합니다. 값이 같으면 true를 반환합니다. 이 테스트는 ReferenceEquals 메서드를 호출하는 것과 같습니다. 또한 objA와 objB가 모두 null 인 경우 메서드는 true를 반환합니다.

objA 또는 objB가 null인지 여부를 판별합니다. 그렇다면 false를 반환합니다.

두 개체가 동일한 개체 참조를 나타내지 않고 둘 다 null 인 경우 objA.Equals (objB)를 호출하고 결과를 반환합니다. 즉, objA가 Object.Equals (Object) 메서드를 재정의하면이 재정의가 호출됩니다.

+0

@AlexD 아 고맙습니다! – McGarnagle

+0

감사합니다! Object.equals 메소드를 완전히 간과했습니다. enum이 올 때 objA.Equals (objB)를 호출하여 실제 값을 평가하거나 enum의 객체를 덮어 쓸 필요가 있다고 가정합니다. Equals? – Kaustix

+0

@Kaustix 예, 열거 형에는 Equals에 대한 자체 재정의가 있습니다. http://msdn.microsoft.com/en-us/library/8bafh2by(v=vs.110).aspx – McGarnagle