Recursively Compare Two Object Arrays
I'm using an external library which returns an object array for the old state and current state of an object (where each item in the array represents the properties and their values). So far i have come up with:
for (var i = 0; i < oldState.Length; i++) { return oldState[i].Equals(state[i]); }
This compares all the top level propert开发者_JAVA技巧ies. But i also wish to drill into some (ones marked with the attribute CompareComplex) of the complex properties and compare for differences between it's properties them aswell. I'd imagine the best way to achieve this would be to use a recursive function. I can't quite get my head around this but i'm sure the solution is quite simple.
I'd really appreciate it if someone could help. Thanks
Your code compares just the first element!
Better:
return oldState.SequenceEquals(state);
To do a "deep compare" override the Equals() method of the "state" class.
An approach to take for the iteration could be is:
- write the code for how'd you compare for a single pair of objects (
oldObject
andobject
) - copy that test into the loop, and set the object at before running the comparison code
like:
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);
}
Importantly, take out that return statement so execution doesn't stop after the the iteration for i == 0
, and keep your results in another object.
cheers for your answers i have managed to come up the the following method:
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;
}
A few things to note:
- The amount of properties in my initial object array doesn't match the number of items in type.GetProperties(). I can't see how i can say whether an object within the object array has the IgnoreLogging attribute so i compare it against the type.
- The ChildLoggingAttribute is used to determine when an attribute is a complex type.
If anyone has any suggestions on how i can improve this then i'd really appreciate it. Thanks
精彩评论