/// <summary> /// Retrieves the changes between <paramref name="oldVersion"/> and <paramref name="newVersion"/>. /// <paramref name="hasChanged"/> will be true if the return value has any entries, false otherwise. /// </summary> /// <param name="newVersion">The properties associated with the new version of the object.</param> /// <param name="oldVersion">The properties associated with the old version of the object.</param> /// <param name="hasChanged">Whether there are any changes.</param> /// <param name="includePropertiesThatHaveNotChanged">If false, the returned collection will have unchanged items removed.</param> /// <returns>The changes.</returns> public static IEnumerable <PropertyValueChange> GetChanges ( this PropertyValues newVersion, PropertyValues oldVersion, out bool hasChanged, bool includePropertiesThatHaveNotChanged = false ) { // Sanity. newVersion = newVersion ?? new PropertyValues(); oldVersion = oldVersion ?? new PropertyValues(); // Will contain all properties, not just changes. var allProps = new List <PropertyValueChange>(); // Loop over new properties and find new or changed values. foreach (PropertyValue newPropVal in newVersion) { allProps.Add ( new PropertyValueChange ( oldVersion?.GetProperty(newPropVal.PropertyDef), newPropVal ) ); } // Loop over old properties to find removed values. if (oldVersion != null) { foreach (PropertyValue oldPropVal in oldVersion) { if (!newVersion.Exists(oldPropVal.PropertyDef)) { allProps.Add(new PropertyValueChange(oldPropVal, null)); } } } // Ignore anything that has not changed. var changedProperties = allProps.Where(p => p.ChangeType != PropertyValueChangeType.None); // Set the out variable. hasChanged = changedProperties.Any(); // Return the changes. return(includePropertiesThatHaveNotChanged ? allProps : changedProperties); }