2015-08-25 2 views
0

У меня есть метод, который проходит через класс и проверяет, имеют ли 2 объекта одинаковые значения.Рекурсивное отражение через объект

private bool LoopThroughObjects<T>(T ob1, T ob2) 
{ 
    Type type = ob1.GetType(); 
    System.Reflection.PropertyInfo[] props = type.GetProperties(); 

    foreach (var prop in props) 
    { 
     object ent1value = prop.GetValue(ob1, new object[] { }); 
     object ent2value = prop.GetValue(ob2, new object[] { }); 

     //If object is in the same namespace it's a nested element 
     if(IsSameNameSpace(type.Namespace, prop.PropertyType.Namespace)) 
     { 
      _depth++; 
      ValidateEntity_AttributesNotSame(ent1value, ent2value); 
     } 
     else 
      ComparerOutput.Add(_conjunction + prop.Name, ent1value.Equals(ent2value)); 

     if (BreakOnUnequally) 
      if (!ent1value.Equals(ent2value)) 
       return false; 
    } 
    return true; 
} 

Пример из объекта, который я могу отправить:

public class RefelctionTestEntity 
{ 
    public int Id { get; set; } 
    public String Firstname { get; set; } 
    public String Lastname { get; set; } 
    public int Age { get; set; } 
    public RefelctionTestEntity Child { get; set;} 
    public Vehicle.Bikes Bike { get; set; } 
} 

Я хожу рекурсивно через объект, поэтому я также проверить Child еп Bike. Мой вопрос - лучший метод для проверки этих внутренних объектов? Что я делаю в данный момент проверить пространство имен объекта против родительского пространства имен внутреннего объекта:

private bool IsSameNameSpace(String baseNamespace, String propertyNamespace) 
{ 
    if (String.IsNullOrEmpty(baseNamespace) || String.IsNullOrEmpty(propertyNamespace)) 
     return true; 

    if (String.IsNullOrEmpty(baseNamespace) || String.IsNullOrEmpty(propertyNamespace)) 
     return false; 

    String[] part = propertyNamespace.Split('.'); 
    return part[0].Equals(baseNamespace); 
} 
+0

Что вы подразумеваете под «вложенным элементом»? На самом деле не совсем ясно, какую семантику вы пытаетесь навязать через пространства имен, но это, возможно, не подходит ... –

+2

Сначала вы должны проверить, являются ли «obj1» и «obj2» одного и того же типа. Ваш код не работает, если 'obj1' является подтипом' obj2' и вводит новое свойство. Изменение 'obj1.GetType()' '' typeof (T) 'решит эту проблему. Зачем вам нужно тестировать пространство имен? Используйте 'Type.IsValueType' и если он не вызывается этим методом рекурсивно. –

+0

Согласитесь с @Verarind, однако это более сложная проблема - вам также нужно отслеживать свойства, которые вы уже сравнили; иначе вы закончите бесконечную рекурсию - если у вас будет var foo = new RefelctionTestEntity(); foo.Child = foo; ты в беде. Посмотрите http://stackoverflow.com/questions/6276439/how-to-compare-complex-objects-as-structures-in-c-sharp-for-unit-tests –

ответ

0
//If object is in the same namespace it's a nested element 

Использование такого правила может быстро стать проблемой в будущем.

Было бы гораздо удобнее, если бы вы указали свойство рекурсивного элемента с интерфейсом и проверили, реализует ли это свойство текущий интерфейс. Если так, просто на один уровень глубже.

В противном случае проверьте, соответствуют ли значениям свойства, которое вы в данный момент сопоставляете для обоих объектов.

var interf = Text.GetType().GetInterface("MyInterface",false); 

Другой подход - использовать атрибут над элементом для его отметки.

Проверка атрибута будет выглядеть следующим образом:

var att = Text.GetType().GetCustomAttributes(typeof(RecursiveTypeAttribute),false); 

Я не хотел бы проверить, если текущее свойство является ссылочным типом, так как вы можете легко ввести свойство ссылочного типа в будущем.

Смежные вопросы