2017-02-06 6 views
1

У меня есть три модели, как описано ниже:Как найти разницу в двух моделях, имеющих свойство собственного списка?

public class ComponentData //Contains list of Component Model 
{ 
    public int id { get; set; } 
    public List<Component> Components { get; set; } 
} 

public class Component //Contains list of ComponentValue Model 
{ 
    public Int32 SiteId { get; set; } 
    public IList<ComponentValue> ComponentValues { get; set; } 
} 

public class ComponentValue //Contains list of it self i.e. ComponentValue Model 
{  
    public String Id { get; set; } 
    public String Name { get; set; } 
    public String DisplayName { get; set; } 
    public IList<ComponentValue> ChildComponents { get; set; } 
} 

Теперь у меня есть два объекта старого ComponentData и новый ComponentData, я хочу сравнить эти два объект и хочу найти, есть ли новый список любой нового ребенок добавляемого или какие-либо изменения в существующем ребенке. Как это сделать?

Примечание: public IList<ComponentValue> ChildComponents { get; set; } может содержать несколько детей в нем рекурсивно.

Я попытался:

using (var e1 = cdOld.Components.GetEnumerator()) 
      using (var e2 = cdNew.Components.GetEnumerator()) 
      { 
       while (e1.MoveNext() && e2.MoveNext()) 
       { 
        var item1 = e1.Current.ComponentValues; 
        var item2 = e2.Current.ComponentValues; 
        using (var i1 = item1.GetEnumerator()) 
        using (var i2 = item2.GetEnumerator()) 
        { 
         while (i1.MoveNext() && i2.MoveNext()) 
         { 
//Here not sure how many children both list has and how to make recursive call 
          var item11 = i1.Current; 
          var item12 = i2.Current; 
          if (item11.Id != item12.Id || item11.Name != item12.Name) 
          { 
           cvlistold.Add(item11); 
           cvlistnew.Add(item12); 
          } 

         } 
        } 


        //var firstNotSecond = item1.Except(item2).ToList(); 
        //var secondNotFirst = item2.Except(item1).ToList(); 
        //var v = item1.Select(a => a.Name).Intersect(item2.Select(b => b.Name)).ToList(); 
        //bool c = !(!firstNotSecond.Any() && !secondNotFirst.Any()); 

       } 
      } 

Скриншот: enter image description here

ответ

0

Использование IEquatable интерфейс (или переопределить Равно и GetHashCode):

public class ComponentValue : IEquatable<ComponentValue> 
{ 
     public String Id { get; set; } 
     public String Name { get; set; } 
     public String DisplayName { get; set; } 
     public IList<ComponentValue> ChildComponents { get; set; } 
     public bool Equals(ComponentValue other) 
     { 
      return Id == other.Id && Name == other.Name; 
     } 
} 

Затем, проверить различие:

bool equals = e1.SequenceEqual(e2); 
+0

В моем случае нет детей не одинаково. – MKumar

0

Я имел аналогичную структуру в одном из моих проектов, с той разницей, что они могли бы содержать больше типов элементов, то один, так что я сделал некоторые отражения код, чтобы посмотреть и сравнить эти:

public static bool Compare (this T obj, T comparer) 
{ 
    bool isOkay = true; 
    foreach(var field in typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 
    { 
     if (!isOkay) break; 

     object value = field.GetValue(obj); 
     object comparerValue = field.GetValue(comparer); 
     Type type = field.FieldType; 
     if(Type.GetTypeCode(type) != TypeCode.Object) 
     { 
      if(type == typeof(IList)) 
      { 
       for(int i = 0; i < ((IList)value).Count; i++) 
       { 
        isOkay = isOkay &&(bool)_GenericCompare.MakeGenericMethod(((IList)value)[i].GetType()).Invoke(((IList)value)[i], ((IList)comparerValue)[i]); 
       } 
      } 
     } 
     else 
     { 
      isOkay = isOkay && value.Equals(comparerValue); 
     } 
    } 
    return isOkay; 
} 

// _GenericVompare is : 
typeof(MeTypeThatHasCompareMethod).GetMethod("Compare", BindingFlags.Static | BindingFlags.Public); 

Это просто сокращенный метод, который я сделал, так что вы должны изменить это для ваших нужд, но в основном это перебирает все пункты IList типизированных поля и Invoke s тот же метод на что предметы.

FYI. Этот метод может быть медленным, как черт на огромных списках, поэтому вы должны реализовать какой-то механизм «кеша» для хранения FieldInfo[] для некоторых типов и _GenericCompareMethodInfo для ускорения процесса.

+0

Спасибо за ответ. Я попробую. – MKumar

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

  • Нет связанных вопросов^_^