Рекурсивно сравнивать два массива объектов - PullRequest
2 голосов
/ 12 января 2011

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

для (var i = 0; i

Это сравнивает все свойства верхнего уровня. Но я также хочу углубиться в некоторые (помеченные атрибутом CompareComplex) сложных свойств и сравнить их различия в свойствах. Я думаю, что лучший способ добиться этого - использовать рекурсивную функцию. Я не могу полностью разобраться с этим, но я уверен, что решение довольно простое.

Я бы очень признателен, если бы кто-то мог помочь. Спасибо

Ответы [ 3 ]

2 голосов
/ 12 января 2011

Ваш код сравнивает только первый элемент!

Лучше:

return oldState.SequenceEquals(state);

Чтобы выполнить "глубокое сравнение", переопределите метод Equals () метода "государственный "класс.

0 голосов
/ 14 января 2011

приветствует ваши ответы. Мне удалось найти следующий метод:

private bool Compare(Type type, string[] propertyNames, object[] oldState, object[] state) {
    // Get the property indexes to ignore
    var propertyIndexesToIgnore = type.GetProperties()
        .Where(p => p.GetCustomAttributes(typeof(IgnoreLoggingAttribute), false).Count() > 0)
        .Select(p => Array.IndexOf(propertyNames, p.Name)).ToArray();

    // Get the child property indexes
    var childPropertyIndexes = type.GetProperties()
        .Where(p => p.GetCustomAttributes(typeof(ChildLoggingAttribute), false).Count() > 0)
        .Select(p => Array.IndexOf(propertyNames, p.Name)).ToArray();

    for (var i = 0; i < oldState.Length; i++) {
        // If we need to check the child properties
        if (childPropertyIndexes.Contains(i)) {
            if (oldState[i] == null)
                break;

            var childPropertyType = oldState[i].GetType();
            var childProperties = oldState[i].GetType().GetProperties();

            // Recursively call this function to check the child properties
            if (Compare(childPropertyType, childProperties.Select(p => p.Name).ToArray(), childProperties.Select(p => p.GetValue(oldState[i], null)).ToArray<object>(), childProperties.Select(p => p.GetValue(state[i], null)).ToArray<object>()))
                return true;
        } else if (!propertyIndexesToIgnore.Contains(i) && ((oldState[i] != null && state[i] != null && !oldState[i].Equals(state[i])) || (oldState[i] != null && state[i] == null) || (oldState[i] == null && state[i] != null)))
            return true;
    }

    return false;
}

Несколько замечаний:

  1. Количество свойств в моем исходном объектемассив не соответствует количеству элементов в type.GetProperties ().Я не могу понять, как я могу сказать, имеет ли объект в массиве объектов атрибут IgnoreLogging, поэтому я сравниваю его с типом.
  2. Атрибут ChildLoggingAttribute используется для определения, когда атрибут является сложным типом.

Если у кого-то есть какие-либо предложения о том, как я могу улучшить это, тогда я был бы очень признателен.Спасибо

0 голосов
/ 12 января 2011

Подход для итерации может быть следующим:

  • напишите код, который вы сравниваете для одной пары объектов (oldObject и object)
  • скопируйте этот тест в цикл и установите объект перед запуском кода сравнения

как:

for (var i = 0; i < oldState.Length; i++)
{
    ObjectType oldObject = oldState[i];
    ObjectType object= state[i];

    \\insert your comparison code here
    oldObject.Property.Equals(object.Property);
}

Важно, уберите этот оператор return, чтобы выполнение не останавливалось после итерации для i == 0, и сохраните результаты в другом объекте.

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