2010-03-24 6 views
4

두 개체를 비교하고 다른 모든 속성 이름 목록을 반환하는 메서드가 있습니다.C#을 사용하여 중첩 된 개체 속성 비교

public class Address 
    { 
     public string AddressLine1 { get; set; } 
     public string AddressLine2 { get; set; } 
     public string City { get; set; } 
     public string State { get; set; } 
     public string Zip { get; set; } 
    } 

     public class Employee 
     { 
      public string FirstName { get; set; } 
      public string MiddleName { get; set; } 
      public string LastName { get; set; } 
      public Address EmployeeAddress { get; set; } 
     } 

나는 다음과 같은 두 직원 인스턴스를 비교하는 것을 시도하고있다 : 나는이 두 직원의 물체를 통과 할 때 그래서

var emp1Address = new Address(); 
     emp1Address.AddressLine1 = "Microsoft Corporation"; 
     emp1Address.AddressLine2 = "One Microsoft Way"; 
     emp1Address.City = "Redmond"; 
     emp1Address.State = "WA"; 
     emp1Address.Zip = "98052-6399"; 

     var emp1 = new Employee(); 
     emp1.FirstName = "Bill"; 
     emp1.LastName = "Gates"; 
     emp1.EmployeeAddress = emp1Address; 


     var emp2Address = new Address(); 
     emp2Address.AddressLine1 = "Gates Foundation"; 
     emp2Address.AddressLine2 = "One Microsoft Way"; 
     emp2Address.City = "Redmond"; 
     emp2Address.State = "WA"; 
     emp2Address.Zip = "98052-6399"; 

     var emp2 = new Employee(); 
     emp2.FirstName = "Melinda"; 
     emp2.LastName = "Gates"; 
     emp2.EmployeeAddress = emp2Address; 

을 다음과 같이 내가이 개 수업을 예를 들어

public static IList<string> GetDifferingProperties(object source, object target) 
{ 
    var sourceType = source.GetType(); 
    var sourceProperties = sourceType.GetProperties(); 
    var targetType = target.GetType(); 
    var targetProperties = targetType.GetProperties(); 

    var properties = (from s in sourceProperties 
         from t in targetProperties 
         where s.Name == t.Name && 
          s.PropertyType == t.PropertyType && 
          s.GetValue(source,null) != t.GetValue(target,null) 
         select s.Name).ToList(); 
    return properties; 
} 

내 GetDifferingProperties 메서드에 현재 그것은 FirstName 및 EmployeeAddress를 반환하지만 EmployeeAddress의 어떤 정확한 속성 (이 경우 Address1)이 변경되었는지는 알려주지 않습니다. EmployeeAddress.Address1과 같은 것을 얻기 위해 어떻게이 방법을 조정할 수 있습니까?

답변

3

!=을 사용하고 있기 때문에 그 이유는 객체의 경우 값이 아닌 객체의 신원을 테스트하기 때문입니다. 핵심은 재귀를 사용하여 속성의 속성 목록을 생성하는 것입니다. 이

public static IList<string> GetDifferingProperties(object source, object target) 
{ 
    var sourceType = source.GetType(); 
    var sourceProperties = sourceType.GetProperties(); 
    var targetType = target.GetType(); 
    var targetProperties = targetType.GetProperties(); 

    var result = new List<string>(); 

    foreach (var property in 
     (from s in sourceProperties 
     from t in targetProperties 
     where s.Name == t.Name && 
     s.PropertyType == t.PropertyType && 
     !Equals(s.GetValue(source, null), t.GetValue(target, null)) 
     select new { Source = s, Target = t })) 
    { 
    // it's up to you to decide how primitive is primitive enough 
    if (IsPrimitive(property.Source.PropertyType)) 
    { 
     result.Add(property.Source.Name); 
    } 
    else 
    { 
     foreach (var subProperty in GetDifferingProperties(
      property.Source.GetValue(source, null), 
      property.Target.GetValue(target, null))) 
     { 
     result.Add(property.Source.Name + "." + subProperty); 
     } 
    } 
    } 

    return result; 
} 

private static bool IsPrimitive(Type type) 
{ 
    return type == typeof(string) || type == typeof(int); 
} 
+0

왜 내가 사용했는지 Isprimitive, 내가 ur 코드를 사용하려고 할 때, 그리고 언제 isPrimitive를 꺼내 나 항상 불일치가되는지 설명 할 수 있습니까? 동일한 부분에 오류가 있습니다. 고맙습니다 – jprbest

0

원 포인트 : 사용자의 메서드에서 EmployeeAddress 속성의 실제 차이를 고려하지 않습니다. 그것을 시험하고보십시오.

 emp2Address.AddressLine1 = emp1Address.AddressLine1;// "Gates Foundation"; 
     emp2Address.AddressLine2 = emp1Address.AddressLine2;// "One Microsoft Way"; 
     emp2Address.City = emp1Address.City;// "Redmond"; 
     emp2Address.State = emp1Address.State;// "WA"; 
     emp2Address.Zip = emp1Address.Zip;// "98052-6399"; 

프로그램은 여전히 ​​EmployeeAddress를 일치하지 않는 속성으로 반환합니다. 그러나 emp2.EmployeeAddress = emp1Address 만 설정하면 "일치하지 않음"메시지가 표시되지 않습니다.

참조에 대해 뭔가 뭔가 ... 하여튼

, 해당 개체에 대한 다른 무엇을 찾을 하려는 경우, 당신은 그 객체에 대해 다른 무엇에 대한 검색해야 할 것입니다.

1

원칙적으로, 당신은 당신이 당신이 GetValue를 사용하여 (그 값을 얻을 후 비교하려는 두 개체에 GetDifferingProperties에 구현 된 기술을 사용해야합니다 ... 깊은 당신이 원하는대로 갈 것입니다 쿼리에서). 당신이 실제로이를 사용하려면

public static IEnumerable<string> GetDifferingProperties 
    (object source, object target) { 

    // Terminate recursion - equal objects don't have any differing properties 
    if (source == target) return new List<string>(); 

    // Compare properties of two objects that are not equal 
    var sourceProperties = source.GetType().GetProperties(); 
    var targetProperties = target.GetType().GetProperties(); 
    return 
    from s in sourceProperties 
    from t in targetProperties 
    where s.Name == t.Name && s.PropertyType == t.PropertyType 
    let sVal = s.GetValue(source, null) 
    let tVal = t.GetValue(target, null) 

    // Instead of comparing the objects directly using '==', we run 
    // the method recursively. If the two objects are equal, it returns 
    // empty list immediately, otherwise it generates multiple properties 
    from name in GetDifferingProperties(sVal, tVal) 
    select name; 
} 

, 당신은 아마 재산에 도착하는 방법을 추적 (유지하려는 것이 코드는 단지 당신을 제공 : 아마 가장 간단한 구현 방법의 재귀를 만드는 것입니다 속성 이름이 들어있는 객체에 대한 정보가없는 속성 이름 목록). 마지막 줄을 select name에서 select s.Name + "." + name으로 변경할 수 있습니다 (예 : Address 회원의 Name 속성 인 경우).

2

나는이 등 중첩 된 개체, 열거, ILists, 프로젝트는 (그냥 1 .cs 파일)를 사용하여 무료로 쉽게 비교 할 수있는 가능성이 http://comparenetobjects.codeplex.com/ 를 사용하는 것이 좋습니다 수 있습니다. 또한, 다른 값을 가져 오거나, 무시할 속성을 추가하는 것이 가능합니다.