Петля через объекты в C #

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

Возможно ли это сделать, не зная, какие свойства содержит объект?

7 Solutions collect form web for “Петля через объекты в C #”

Да, с reflectionм – при условии, что каждый тип свойства реализует Equals соответствующим образом. Альтернативой будет использование ReflectiveEquals рекурсивно для всех, кроме некоторых известных типов, но это становится сложным.

 public bool ReflectiveEquals(object first, object second) { if (first == null && second == null) { return true; } if (first == null || second == null) { return false; } Type firstType = first.GetType(); if (second.GetType() != firstType) { return false; // Or throw an exception } // This will only use public properties. Is that enough? foreach (PropertyInfo propertyInfo in firstType.GetProperties()) { if (propertyInfo.CanRead) { object firstValue = propertyInfo.GetValue(first, null); object secondValue = propertyInfo.GetValue(second, null); if (!object.Equals(firstValue, secondValue)) { return false; } } } return true; } 

Конечно, вы можете с reflectionм. Вот код для захвата свойств данного типа.

 var info = typeof(SomeType).GetProperties(); 

Если вы можете дать больше информации о том, что вы сравниваете по свойствам, мы можем собрать базовый различный алгоритм n. Этот код для intstance будет отличаться от имен

 public bool AreDifferent(Type t1, Type t2) { var list1 = t1.GetProperties().OrderBy(x => x.Name).Select(x => x.Name); var list2 = t2.GetProperties().OrderBy(x => x.Name).Select(x => x.Name); return list1.SequenceEqual(list2); } 

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

 ///  /// Utility class for comparing objects. ///  public static class ObjectComparer { ///  /// Compares the public properties of any 2 objects and determines if the properties of each /// all contain the same value. ///  /// In cases where object1 and object2 are of different Types (both being derived from Type T) /// we will cast both objects down to the base Type T to ensure the property comparison is only /// completed on COMMON properties. /// (ex. Type T is Foo, object1 is GoodFoo and object2 is BadFoo -- both being inherited from Foo -- /// both objects will be cast to Foo for comparison) ///  ///  /// Any class with public properties. /// Object to compare to object2. /// Object to compare to object1. /// A List of  objects that contain data on the properties /// from object1 that are not equal to the corresponding properties of object2. /// A boolean value indicating whether or not the properties of each object match. public static bool GetDifferentProperties ( T object1 , T object2 , out List propertyInfoList ) where T : class { return GetDifferentProperties( object1 , object2 , null , out propertyInfoList ); } ///  /// Compares the public properties of any 2 objects and determines if the properties of each /// all contain the same value. ///  /// In cases where object1 and object2 are of different Types (both being derived from Type T) /// we will cast both objects down to the base Type T to ensure the property comparison is only /// completed on COMMON properties. /// (ex. Type T is Foo, object1 is GoodFoo and object2 is BadFoo -- both being inherited from Foo -- /// both objects will be cast to Foo for comparison) ///  ///  /// Any class with public properties. /// Object to compare to object2. /// Object to compare to object1. /// A list of  objects /// to ignore when completing the comparison. /// A List of  objects that contain data on the properties /// from object1 that are not equal to the corresponding properties of object2. /// A boolean value indicating whether or not the properties of each object match. public static bool GetDifferentProperties ( T object1 , T object2 , List ignoredProperties , out List propertyInfoList ) where T : class { propertyInfoList = new List(); // If either object is null, we can't compare anything if ( object1 == null || object2 == null ) { return false; } Type object1Type = object1.GetType(); Type object2Type = object2.GetType(); // In cases where object1 and object2 are of different Types (both being derived from Type T) // we will cast both objects down to the base Type T to ensure the property comparison is only // completed on COMMON properties. // (ex. Type T is Foo, object1 is GoodFoo and object2 is BadFoo -- both being inherited from Foo -- // both objects will be cast to Foo for comparison) if ( object1Type != object2Type ) { object1Type = typeof ( T ); object2Type = typeof ( T ); } // Remove any properties to be ignored List comparisonProps = RemoveProperties( object1Type.GetProperties() , ignoredProperties ); foreach ( PropertyInfo object1Prop in comparisonProps ) { Type propertyType = null; object object1PropValue = null; object object2PropValue = null; // Rule out an attempt to check against a property which requires // an index, such as one accessed via this[] if ( object1Prop.GetIndexParameters().GetLength( 0 ) == 0 ) { // Get the value of each property object1PropValue = object1Prop.GetValue( object1 , null ); object2PropValue = object2Type.GetProperty( object1Prop.Name ).GetValue( object2 , null ); // As we are comparing 2 objects of the same type we know // that they both have the same properties, so grab the // first non-null value if ( object1PropValue != null ) propertyType = object1PropValue.GetType().GetInterface( "IComparable" ); if ( propertyType == null ) if ( object2PropValue != null ) propertyType = object2PropValue.GetType().GetInterface( "IComparable" ); } // If both objects have null values or were indexed properties, don't continue if ( propertyType != null ) { // If one property value is null and the other is not null, // they aren't equal; this is done here as a native CompareTo // won't work with a null value as the target if ( object1PropValue == null || object2PropValue == null ) { propertyInfoList.Add( object1Prop ); } else { // Use the native CompareTo method MethodInfo nativeCompare = propertyType.GetMethod( "CompareTo" ); // Sanity Check: // If we don't have a native CompareTo OR both values are null, we can't compare; // hence, we can't confirm the values differ... just go to the next property if ( nativeCompare != null ) { // Return the native CompareTo result bool equal = ( 0 == (int) ( nativeCompare.Invoke( object1PropValue , new object[] {object2PropValue} ) ) ); if ( !equal ) { propertyInfoList.Add( object1Prop ); } } } } } return propertyInfoList.Count == 0; } ///  /// Compares the public properties of any 2 objects and determines if the properties of each /// all contain the same value. ///  /// In cases where object1 and object2 are of different Types (both being derived from Type T) /// we will cast both objects down to the base Type T to ensure the property comparison is only /// completed on COMMON properties. /// (ex. Type T is Foo, object1 is GoodFoo and object2 is BadFoo -- both being inherited from Foo -- /// both objects will be cast to Foo for comparison) ///  ///  /// Any class with public properties. /// Object to compare to object2. /// Object to compare to object1. /// A boolean value indicating whether or not the properties of each object match. public static bool HasSamePropertyValues ( T object1 , T object2 ) where T : class { return HasSamePropertyValues( object1 , object2 , null ); } ///  /// Compares the public properties of any 2 objects and determines if the properties of each /// all contain the same value. ///  /// In cases where object1 and object2 are of different Types (both being derived from Type T) /// we will cast both objects down to the base Type T to ensure the property comparison is only /// completed on COMMON properties. /// (ex. Type T is Foo, object1 is GoodFoo and object2 is BadFoo -- both being inherited from Foo -- /// both objects will be cast to Foo for comparison) ///  ///  /// Any class with public properties. /// Object to compare to object2. /// Object to compare to object1. /// A list of  objects /// to ignore when completing the comparison. /// A boolean value indicating whether or not the properties of each object match. public static bool HasSamePropertyValues ( T object1 , T object2 , List ignoredProperties ) where T : class { // If either object is null, we can't compare anything if ( object1 == null || object2 == null ) { return false; } Type object1Type = object1.GetType(); Type object2Type = object2.GetType(); // In cases where object1 and object2 are of different Types (both being derived from Type T) // we will cast both objects down to the base Type T to ensure the property comparison is only // completed on COMMON properties. // (ex. Type T is Foo, object1 is GoodFoo and object2 is BadFoo -- both being inherited from Foo -- // both objects will be cast to Foo for comparison) if ( object1Type != object2Type ) { object1Type = typeof ( T ); object2Type = typeof ( T ); } // Remove any properties to be ignored List comparisonProps = RemoveProperties( object1Type.GetProperties() , ignoredProperties ); foreach ( PropertyInfo object1Prop in comparisonProps ) { Type propertyType = null; object object1PropValue = null; object object2PropValue = null; // Rule out an attempt to check against a property which requires // an index, such as one accessed via this[] if ( object1Prop.GetIndexParameters().GetLength( 0 ) == 0 ) { // Get the value of each property object1PropValue = object1Prop.GetValue( object1 , null ); object2PropValue = object2Type.GetProperty( object1Prop.Name ).GetValue( object2 , null ); // As we are comparing 2 objects of the same type we know // that they both have the same properties, so grab the // first non-null value if ( object1PropValue != null ) propertyType = object1PropValue.GetType().GetInterface( "IComparable" ); if ( propertyType == null ) if ( object2PropValue != null ) propertyType = object2PropValue.GetType().GetInterface( "IComparable" ); } // If both objects have null values or were indexed properties, don't continue if ( propertyType != null ) { // If one property value is null and the other is not null, // they aren't equal; this is done here as a native CompareTo // won't work with a null value as the target if ( object1PropValue == null || object2PropValue == null ) { return false; } // Use the native CompareTo method MethodInfo nativeCompare = propertyType.GetMethod( "CompareTo" ); // Sanity Check: // If we don't have a native CompareTo OR both values are null, we can't compare; // hence, we can't confirm the values differ... just go to the next property if ( nativeCompare != null ) { // Return the native CompareTo result bool equal = ( 0 == (int) ( nativeCompare.Invoke( object1PropValue , new object[] {object2PropValue} ) ) ); if ( !equal ) { return false; } } } } return true; } ///  /// Removes any  object in the supplied List of /// properties from the supplied Array of properties. ///  /// Array containing master list of ///  objects. /// List of  objects to /// remove from the supplied array of properties. /// A List of  objects. private static List RemoveProperties ( IEnumerable allProperties , IEnumerable propertiesToRemove ) { List innerPropertyList = new List(); // Add all properties to a list for easy manipulation foreach ( PropertyInfo prop in allProperties ) { innerPropertyList.Add( prop ); } // Sanity check if ( propertiesToRemove != null ) { // Iterate through the properties to ignore and remove them from the list of // all properties, if they exist foreach ( PropertyInfo ignoredProp in propertiesToRemove ) { if ( innerPropertyList.Contains( ignoredProp ) ) { innerPropertyList.Remove( ignoredProp ); } } } return innerPropertyList; } } 

Реальная проблема: как получить разницу в двух наборах?

Самый быстрый способ, который я нашел, – сначала преобразовать наборы в словари, а затем разложить их. Вот общий подход:

 static IEnumerable DictionaryDiff(Dictionary d1, Dictionary d2) { return from x in d1 where !d2.ContainsKey(x.Key) select x.Value; } 

Тогда вы можете сделать что-то вроде этого:

 static public IEnumerable PropertyDiff(Type t1, Type t2) { var d1 = t1.GetProperties().ToDictionary(x => x.Name); var d2 = t2.GetProperties().ToDictionary(x => x.Name); return DictionaryDiff(d1, d2); } 

Сравнение двух объектов одного типа с использованием LINQ и Reflection. NB! Это в основном переписывание решения от Jon Skeet, но с более компактным и современным синтаксисом. Он должен также генерировать немного более эффективный IL.

Это выглядит примерно так:

 public bool ReflectiveEquals(LocalHdTicket serverTicket, LocalHdTicket localTicket) { if (serverTicket == null && localTicket == null) return true; if (serverTicket == null || localTicket == null) return false; var firstType = serverTicket.GetType(); // Handle type mismatch anyway you please: if(localTicket.GetType() != firstType) throw new Exception("Trying to compare two different object types!"); return !(from propertyInfo in firstType.GetProperties() where propertyInfo.CanRead let serverValue = propertyInfo.GetValue(serverTicket, null) let localValue = propertyInfo.GetValue(localTicket, null) where !Equals(serverValue, localValue) select serverValue).Any(); } 

Да. Используйте Reflection . С Reflection вы можете делать такие вещи, как:

 //given object of some type object myObjectFromSomewhere; Type myObjOriginalType = myObjectFromSomewhere.GetType(); PropertyInfo[] myProps = myObjOriginalType.GetProperties(); 

И тогда вы можете использовать полученные classы PropertyInfo для сравнения всех вещей.

Type.GetProperties будет перечислять каждое из свойств данного типа. Затем используйте PropertyInfo.GetValue для проверки значений.

  • Использование LINQ для удаления элементов из списка
  • как преобразовать opencv cv :: Mat в qimage
  • Создайте строго типизированный объект c # из объекта json с ID как имя
  • Является ли bool родным C-типом?
  • Почему у нас нет виртуального конструктора на C ++?
  • Изменение номера порта проекта в Visual Studio 2013
  • Оценить строку с помощью математических операторов
  • Есть ли простой способ превратить int в массив ints каждой цифры?
  • Есть ли способ найти адрес ссылки?
  • Перегрузка и переопределение
  • Глубокая копия списка
  • Interesting Posts

    В чем разница между прокси-сервером и VPN?

    Как синхронизировать SkyDrive / OneDrive в Windows 8.1 при входе на ПК с локальной учетной записью?

    Медленная передача с помощью карты памяти (819 кбит / с)

    ЖДИТЕ для «любого процесса», чтобы закончить

    Приложения теряют фокус в течение нескольких секунд в Windows 7

    Как найти GCD, LCM для набора чисел

    Вращение элемента анимации

    есть ли api в jqgrid для добавления расширенных фильтров для публикации данных?

    Поиск переменных оболочки по имени, косвенно

    Как добавить, отредактировать или управлять пользовательскими поисковыми системами в Opera 15 или более поздних версиях (на основе Chromium)?

    Стандартным клавишам F * требуется удерживать клавишу Fn на Compaq CQ62

    Правильный способ записи строки в файл?

    Карта памяти, не обнаруженная на ПК

    GetFiles с несколькими расширениями

    Должен ли я получить интегрированную графику, если у меня уже есть выделенный графический процессор?

    Давайте будем гением компьютера.