示例#1
0
 /// <summary>
 /// Compare two objects for value differences
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="left"></param>
 /// <param name="right"></param>
 /// <param name="comparisonOptions">Specify the comparison options</param>
 /// <param name="diffOptions">Specify custom diff options</param>
 /// <param name="propertiesToExcludeOrInclude"></param>
 /// <returns></returns>
 public List <Difference> ComputeDiff <T>(T left, T right, ComparisonOptions comparisonOptions, DiffOptions diffOptions, params Expression <Func <T, object> >[] propertiesToExcludeOrInclude)
 {
     return(ComputeDiff(left, right, DefaultMaxDepth, comparisonOptions, diffOptions, propertiesToExcludeOrInclude));
 }
示例#2
0
        /// <summary>
        /// Recurse the object's tree
        /// </summary>
        /// <param name="left">The left object to compare</param>
        /// <param name="right">The right object to compare</param>
        /// <param name="parent">The parent object</param>
        /// <param name="differences">A list of differences currently found in the tree</param>
        /// <param name="currentDepth">The current depth of the tree recursion</param>
        /// <param name="maxDepth">The maximum number of tree children to recurse</param>
        /// <param name="objectTree">A hash table containing the tree that has already been traversed, to prevent recursion loops</param>
        /// <param name="comparisonOptions">Specify the comparison options</param>
        /// <param name="diffOptions">Specify custom diff options</param>
        /// <param name="propertiesToExcludeOrInclude">A list of property names or full path names to include/exclude. Default is <seealso cref="ComparisonOptions.ExcludeList"/>. Specify <seealso cref="ComparisonOptions.ExcludeList"/> to exclude the specified properties from the Diff or <seealso cref="ComparisonOptions.IncludeList"/> to only Diff properties contained in the list.</param>
        /// <param name="path">The current path</param>
        /// <returns></returns>
        private List <Difference> RecurseProperties(object left, object right, object parent, List <Difference> differences, int currentDepth, int maxDepth, ObjectHashcodeMap objectTree, string path, ComparisonOptions comparisonOptions, ICollection <string> propertiesToExcludeOrInclude, DiffOptions diffOptions)
        {
            if (!comparisonOptions.BitwiseHasFlag(ComparisonOptions.AllowCompareDifferentObjects) &&
                left != null && right != null &&
                left?.GetType() != right?.GetType())
            {
                throw new ArgumentException("Objects Left and Right must be of the same type.");
            }

            if (left == null && right == null)
            {
                return(differences);
            }

            if (maxDepth > 0 && currentDepth >= maxDepth)
            {
                return(differences);
            }

            var type = left != null?left.GetType() : right.GetType();

            var typeSupport = type.GetExtendedType(DefaultTypeSupportOptions);

            if (typeSupport.Attributes.Any(x => diffOptions.AttributeIgnoreList.Contains(x)))
            {
                return(differences);
            }
            if (typeSupport.IsDelegate)
            {
                return(differences);
            }

            if (comparisonOptions.BitwiseHasFlag(ComparisonOptions.AllowEqualsOverride))
            {
                // if the object has a custom equality comparitor, use its output (isObjectEqual) instead of iterating the object.
                // if it does not have one specified, this method will return false
                if (CompareForObjectEquality(typeSupport, left, right, out var isObjectEqual) && isObjectEqual)
                {
                    return(differences); // no differences found, no need to continue
                }
            }

            // increment the current recursion depth
            currentDepth++;

            // construct a hashtable of objects we have already inspected (simple recursion loop preventer)
            // we use this hashcode method as it does not use any custom hashcode handlers the object might implement
            if (left != null)
            {
                if (objectTree?.Contains(left) == true)
                {
                    return(differences);
                }
                objectTree?.Add(left);
            }

            // get list of properties
            var properties = new List <ExtendedProperty>();

            if (comparisonOptions.BitwiseHasFlag(ComparisonOptions.CompareProperties))
            {
                properties.AddRange(left.GetProperties(PropertyOptions.All));
            }

            // get all fields, except for backed auto-property fields
            var fields = new List <ExtendedField>();

            if (comparisonOptions.BitwiseHasFlag(ComparisonOptions.CompareFields))
            {
                fields.AddRange(left.GetFields(FieldOptions.All));
                fields = fields.Where(x => !x.IsBackingField).ToList();
            }

            var rootPath  = path;
            var localPath = string.Empty;

            foreach (var property in properties)
            {
                localPath = $"{rootPath}.{property.Name}";
                object leftValue = null;
                try
                {
                    if (left != null)
                    {
                        leftValue = left.GetPropertyValue(property);
                    }
                }
                catch (Exception)
                {
                    // catch any exceptions accessing the property
                }
                object rightValue = null;
                try
                {
                    if (right != null)
                    {
                        rightValue = right.GetPropertyValue(property);
                    }
                }
                catch (Exception)
                {
                    // catch any exceptions accessing the property
                }
                differences = GetDifferences(property.Name, property.Type, GetTypeConverter(property), property.CustomAttributes, leftValue, rightValue, parent, differences, currentDepth, maxDepth, objectTree, localPath, comparisonOptions, propertiesToExcludeOrInclude, diffOptions);
            }
            foreach (var field in fields)
            {
                localPath = $"{rootPath}.{field.Name}";
                object leftValue = null;
                if (left != null)
                {
                    leftValue = left.GetFieldValue(field);
                }
                object rightValue = null;
                if (right != null)
                {
                    rightValue = right.GetFieldValue(field);
                }
                differences = GetDifferences(field.Name, field.Type, GetTypeConverter(field), field.CustomAttributes, leftValue, rightValue, parent, differences, currentDepth, maxDepth, objectTree, localPath, comparisonOptions, propertiesToExcludeOrInclude, diffOptions);
            }

            return(differences);
        }
示例#3
0
        /// <summary>
        /// Get the differences between two objects
        /// </summary>
        /// <param name="propertyName">The name of the property being compared</param>
        /// <param name="propertyType">The type of property being compared. The left property is assumed unless allowCompareDifferentObjects=true</param>
        /// <param name="typeConverter">An optional TypeConverter to treat the type as a different type</param>
        /// <param name="left">The left object to compare</param>
        /// <param name="right">The right object to compare</param>
        /// <param name="parent">The parent object</param>
        /// <param name="differences">A list of differences currently found in the tree</param>
        /// <param name="currentDepth">The current depth of the tree recursion</param>
        /// <param name="maxDepth">The maximum number of tree children to recurse</param>
        /// <param name="objectTree">A hash table containing the tree that has already been traversed, to prevent recursion loops</param>
        /// <param name="path">The current path</param>
        /// <param name="options">Specify the comparison options</param>
        /// <param name="propertiesToExcludeOrInclude">A list of property names or full path names to include/exclude. Default is <seealso cref="ComparisonOptions.ExcludeList"/>. Specify <seealso cref="ComparisonOptions.ExcludeList"/> to exclude the specified properties from the Diff or <seealso cref="ComparisonOptions.IncludeList"/> to only Diff properties contained in the list.</param>
        /// <param name="diffOptions">Specify custom diff options</param>
        /// <returns></returns>
        private List <Difference> GetDifferences(string propertyName, Type propertyType, TypeConverter typeConverter, IEnumerable <CustomAttributeData> attributes, object left, object right, object parent, List <Difference> differences, int currentDepth, int maxDepth, ObjectHashcodeMap objectTree, string path, ComparisonOptions options, ICollection <string> propertiesToExcludeOrInclude, DiffOptions diffOptions)
        {
            var propertyTypeSupport = propertyType.GetExtendedType(DefaultTypeSupportOptions);
            var isCollection        = propertyType != typeof(string) && propertyType.GetInterface(nameof(IEnumerable)) != null;

            object leftValue  = null;
            object rightValue = null;

            leftValue = left;

            if (options.BitwiseHasFlag(ComparisonOptions.AllowCompareDifferentObjects) && rightValue != null)
            {
                rightValue = GetValueForProperty(right, propertyName);
            }
            else
            {
                rightValue = right;
            }

            if (!isCollection || (isCollection && !options.BitwiseHasFlag(ComparisonOptions.TreatEmptyListAndNullTheSame)))
            {
                if (rightValue == null && leftValue != null || leftValue == null && rightValue != null)
                {
                    if (GetPropertyInclusionState(propertyName, path, options, propertiesToExcludeOrInclude, attributes, diffOptions.AttributeIgnoreList) == FilterResult.Include)
                    {
                        differences.Add(new Difference((leftValue ?? rightValue).GetType(), propertyName, path, leftValue, rightValue, typeConverter));
                    }
                    return(differences);
                }
            }

            if (leftValue == null && rightValue == null)
            {
                return(differences);
            }

            var leftValueType  = leftValue?.GetType() ?? propertyType;
            var rightValueType = rightValue?.GetType() ?? propertyType;

            if (isCollection && options.BitwiseHasFlag(ComparisonOptions.CompareCollections))
            {
                var genericArguments = propertyType.GetGenericArguments();
                var isArray          = propertyTypeSupport.IsArray;
                var elementType      = propertyTypeSupport.ElementType;
                // iterate the collection
                var aValueCollection      = (leftValue as IEnumerable);
                var aValueCollectionCount = GetCountFromEnumerable(aValueCollection);
                var bValueCollection      = (rightValue as IEnumerable);
                var bValueCollectionCount = GetCountFromEnumerable(bValueCollection);
                var bValueEnumerator      = bValueCollection?.GetEnumerator();
                if (options.BitwiseHasFlag(ComparisonOptions.TreatEmptyListAndNullTheSame) &&
                    aValueCollectionCount == 0 && bValueCollectionCount == 0)
                {
                    // skip collection equality check, they both have no elements or are null
                    return(differences);
                }

                if (aValueCollection != null)
                {
                    var leftIndex    = 0;
                    var matchTracker = new MatchTracker();
                    // compare elements must be the same order
                    foreach (var collectionItem in aValueCollection)
                    {
                        // iterate the left side
                        leftValue = collectionItem;
                        matchTracker.AddLeft(leftValue, leftIndex);
                        var hasMatch = false;
                        var hasValue = false;
                        if (options.BitwiseHasFlag(ComparisonOptions.AllowCollectionsToBeOutOfOrder))
                        {
                            bValueEnumerator?.Reset();
                        }
                        var rightIndex = 0;
                        do
                        {
                            // iterate the right side
                            ObjectHashcodeMap childObjectTree = null;
                            // we can't use the object tree here when allowing out of order collections because we will compare the same collection element multiple times.
                            if (!options.BitwiseHasFlag(ComparisonOptions.AllowCollectionsToBeOutOfOrder))
                            {
                                childObjectTree = objectTree;
                            }
                            hasValue = bValueEnumerator?.MoveNext() ?? false;
                            if (!hasValue)
                            {
                                if (leftIndex == rightIndex)
                                {
                                    // left has a value in collection, right does not. That's a difference
                                    if (GetPropertyInclusionState(propertyName, path, options, propertiesToExcludeOrInclude, attributes, diffOptions.AttributeIgnoreList) == FilterResult.Include)
                                    {
                                        differences.Add(new Difference(leftValue?.GetType() ?? elementType, propertyName, path, leftIndex, leftValue, null, typeConverter));
                                    }
                                }
                                break;
                            }

                            rightValue = bValueEnumerator?.Current;
                            matchTracker.AddRight(rightValue, rightIndex);
                            rightIndex++;
                            if (leftValue == null && rightValue == null)
                            {
                                continue;
                            }
                            if (leftValue == null && rightValue != null)
                            {
                                continue;
                            }
                            // check array element for difference
                            if (leftValue != null && !leftValue.GetType().IsValueType&& leftValue.GetType() != typeof(string))
                            {
                                var itemDifferences = RecurseProperties(leftValue, rightValue, parent, new List <Difference>(), currentDepth, maxDepth, childObjectTree, path, options, propertiesToExcludeOrInclude, diffOptions);
                                if (itemDifferences.Any() && options.BitwiseHasFlag(ComparisonOptions.AllowCollectionsToBeOutOfOrder))
                                {
                                    continue;
                                }
                                else if (itemDifferences.Any())
                                {
                                    differences.AddRange(itemDifferences);
                                    hasMatch = true;
                                }
                                else
                                {
                                    hasMatch = true;
                                }
                            }
                            else if (leftValue != null && leftValue.GetType().IsGenericType&& leftValue.GetType().GetGenericTypeDefinition() == typeof(KeyValuePair <,>))
                            {
                                // compare keys and values of a KVP
                                var leftKvpKey    = GetValueForProperty(leftValue, "Key");
                                var leftKvpValue  = GetValueForProperty(leftValue, "Value");
                                var rightKvpKey   = GetValueForProperty(rightValue, "Key");
                                var rightKvpValue = GetValueForProperty(rightValue, "Value");

                                var leftKvpKeyType   = leftKvpKey?.GetType() ?? genericArguments.First();
                                var leftKvpValueType = leftKvpValue?.GetType() ?? genericArguments.Skip(1).First();

                                // compare the key
                                if (leftKvpKey != null && !leftKvpKeyType.IsValueType && leftKvpKeyType != typeof(string))
                                {
                                    var itemDifferences = RecurseProperties(leftKvpKey, rightKvpKey, leftValue, new List <Difference>(), currentDepth, maxDepth, childObjectTree, path, options, propertiesToExcludeOrInclude, diffOptions);
                                    if (itemDifferences.Any() && options.BitwiseHasFlag(ComparisonOptions.AllowCollectionsToBeOutOfOrder))
                                    {
                                        continue;
                                    }
                                    else if (itemDifferences.Any())
                                    {
                                        if (GetPropertyInclusionState(propertyName, path, options, propertiesToExcludeOrInclude, attributes, diffOptions.AttributeIgnoreList) == FilterResult.Include)
                                        {
                                            differences.AddRange(itemDifferences);
                                        }
                                        hasMatch = true;
                                    }
                                    else
                                    {
                                        hasMatch = true;
                                    }
                                }
                                else
                                {
                                    if (!IsMatch(leftKvpKey, rightKvpKey))
                                    {
                                        if (options.BitwiseHasFlag(ComparisonOptions.AllowCollectionsToBeOutOfOrder))
                                        {
                                            continue;
                                        }
                                        if (GetPropertyInclusionState(propertyName, path, options, propertiesToExcludeOrInclude, attributes, diffOptions.AttributeIgnoreList) == FilterResult.Include)
                                        {
                                            differences.Add(new Difference(leftKvpKeyType, propertyName, path, leftIndex, leftKvpKey, rightKvpKey, typeConverter));
                                        }
                                        hasMatch = true;
                                        break;
                                    }
                                    else
                                    {
                                        hasMatch = true;
                                    }
                                }

                                // compare the value
                                if (leftKvpValue != null && !leftKvpValueType.IsValueType && leftKvpValueType != typeof(string))
                                {
                                    var itemDifferences = RecurseProperties(leftKvpValue, rightKvpValue, leftValue, new List <Difference>(), currentDepth, maxDepth, childObjectTree, path, options, propertiesToExcludeOrInclude, diffOptions);
                                    if (itemDifferences.Any() && options.BitwiseHasFlag(ComparisonOptions.AllowCollectionsToBeOutOfOrder))
                                    {
                                        continue;
                                    }
                                    else if (itemDifferences.Any())
                                    {
                                        if (GetPropertyInclusionState(propertyName, path, options, propertiesToExcludeOrInclude, attributes, diffOptions.AttributeIgnoreList) == FilterResult.Include)
                                        {
                                            differences.AddRange(itemDifferences);
                                        }
                                        hasMatch = true;
                                    }
                                    else
                                    {
                                        hasMatch = true;
                                    }
                                }
                                else
                                {
                                    if (!IsMatch(leftValue, rightValue))
                                    {
                                        if (options.BitwiseHasFlag(ComparisonOptions.AllowCollectionsToBeOutOfOrder))
                                        {
                                            continue;
                                        }
                                        if (GetPropertyInclusionState(propertyName, path, options, propertiesToExcludeOrInclude, attributes, diffOptions.AttributeIgnoreList) == FilterResult.Include)
                                        {
                                            differences.Add(new Difference(leftKvpValueType, propertyName, path, leftIndex, leftKvpValue, rightKvpValue, typeConverter));
                                        }
                                        hasMatch = true;
                                        break;
                                    }
                                    else
                                    {
                                        hasMatch = true;
                                    }
                                }
                            }
                            else
                            {
                                if (!IsMatch(leftValue, rightValue))
                                {
                                    if (options.BitwiseHasFlag(ComparisonOptions.AllowCollectionsToBeOutOfOrder))
                                    {
                                        continue;
                                    }
                                    if (GetPropertyInclusionState(propertyName, path, options, propertiesToExcludeOrInclude, attributes, diffOptions.AttributeIgnoreList) == FilterResult.Include)
                                    {
                                        differences.Add(new Difference(leftValue?.GetType() ?? elementType, propertyName, path, leftIndex, leftValue, rightValue, typeConverter));
                                    }
                                    hasMatch = true;
                                    break;
                                }
                                else
                                {
                                    hasMatch = true;
                                }
                            }
                            if (hasMatch)
                            {
                                matchTracker.MatchLeft(leftValue, leftIndex);
                                matchTracker.MatchRight(rightValue, rightIndex - 1);
                            }
                        } while (hasValue && !hasMatch);
                        leftIndex++;
                    }

                    // check which elements were not matched to anything
                    var rightUnmatched = matchTracker.GetRightUnmatched();
                    foreach (var unmatchedElement in rightUnmatched)
                    {
                        // dont add a difference if we already detected it
                        if (!differences.Where(x => x.ArrayIndex == unmatchedElement.ArrayIndex && x.RightValue == unmatchedElement.Object).Any())
                        {
                            if (GetPropertyInclusionState(propertyName, path, options, propertiesToExcludeOrInclude, attributes, diffOptions.AttributeIgnoreList) == FilterResult.Include)
                            {
                                differences.Add(new Difference(unmatchedElement.Object?.GetType() ?? elementType, propertyName, path, unmatchedElement.ArrayIndex, null, unmatchedElement.Object, typeConverter));
                            }
                        }
                    }
                    var leftUnmatched = matchTracker.GetLeftUnmatched();
                    foreach (var unmatchedElement in leftUnmatched)
                    {
                        // dont add a difference if we already detected it
                        if (!differences.Where(x => x.ArrayIndex == unmatchedElement.ArrayIndex && x.LeftValue == unmatchedElement.Object).Any())
                        {
                            if (GetPropertyInclusionState(propertyName, path, options, propertiesToExcludeOrInclude, attributes, diffOptions.AttributeIgnoreList) == FilterResult.Include)
                            {
                                differences.Add(new Difference(unmatchedElement.Object?.GetType() ?? elementType, propertyName, path, unmatchedElement.ArrayIndex, unmatchedElement.Object, null, typeConverter));
                            }
                        }
                    }

                    if (bValueCollectionCount > leftIndex)
                    {
                        // right side has extra elements
                        var rightSideExtraElements = bValueCollectionCount - leftIndex;
                        if (bValueEnumerator != null)
                        {
                            for (var i = 0; i < rightSideExtraElements; i++)
                            {
                                var hasValue = bValueEnumerator?.MoveNext() ?? false;
                                if (hasValue)
                                {
                                    if (GetPropertyInclusionState(propertyName, path, options, propertiesToExcludeOrInclude, attributes, diffOptions.AttributeIgnoreList) == FilterResult.Include)
                                    {
                                        differences.Add(new Difference(aValueCollection.GetType(), propertyName, path, leftIndex, null, bValueEnumerator.Current, typeConverter));
                                    }
                                    leftIndex++;
                                }
                            }
                        }
                    }
                    matchTracker.Dispose();
                }
            }
            else if (!leftValueType.IsValueType && leftValueType != typeof(string))
            {
                if (leftValueType != rightValueType && leftValueType.BaseType == rightValueType.BaseType)
                {
                    if (GetPropertyInclusionState(propertyName, path, options, propertiesToExcludeOrInclude, attributes, diffOptions.AttributeIgnoreList) == FilterResult.Include)
                    {
                        differences.Add(new Difference(propertyType, propertyName, path, leftValue, rightValue, typeConverter));
                    }
                }
                else
                {
                    differences = RecurseProperties(leftValue, rightValue, leftValue, differences, currentDepth, maxDepth, objectTree, path, options, propertiesToExcludeOrInclude, diffOptions);
                }
            }
            else
            {
                if (!IsMatch(leftValue, rightValue))
                {
                    if (GetPropertyInclusionState(propertyName, path, options, propertiesToExcludeOrInclude, attributes, diffOptions.AttributeIgnoreList) == FilterResult.Include)
                    {
                        differences.Add(new Difference(propertyType, propertyName, path, leftValue, rightValue, typeConverter));
                    }
                }
            }

            return(differences);
        }
示例#4
0
 /// <summary>
 /// Compare two objects for value differences
 /// </summary>
 /// <param name="left"></param>
 /// <param name="right"></param>
 /// <param name="maxDepth"></param>
 /// <param name="comparisonOptions">Specify the comparison options</param>
 /// <param name="diffOptions">Specify custom diff options</param>
 /// <param name="propertiesToExcludeOrInclude">A list of property names or full path names to include/exclude. Default is <seealso cref="ComparisonOptions.ExcludeList"/>. Specify <seealso cref="ComparisonOptions.ExcludeList"/> to exclude the specified properties from the Diff or <seealso cref="ComparisonOptions.IncludeList"/> to only Diff properties contained in the list.</param>
 /// <returns></returns>
 public List <Difference> ComputeDiff(object left, object right, int maxDepth, ComparisonOptions comparisonOptions, DiffOptions diffOptions, params string[] propertiesToExcludeOrInclude)
 {
     return(RecurseProperties(left, right, null, new List <Difference>(), 0, maxDepth, new ObjectHashcodeMap(), string.Empty, comparisonOptions, propertiesToExcludeOrInclude, diffOptions));
 }
示例#5
0
        /// <summary>
        /// Compare two objects for value differences
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="left">Object A</param>
        /// <param name="right">Object B</param>
        /// <param name="maxDepth">Maximum recursion depth</param>
        /// <param name="comparisonOptions">Specify the comparison options</param>
        /// <param name="diffOptions">Specify custom diff options</param>
        /// <param name="propertiesToExcludeOrInclude">A list of property names or full path names to include/exclude. Default is <seealso cref="ComparisonOptions.ExcludeList"/>. Specify <seealso cref="ComparisonOptions.ExcludeList"/> to exclude the specified properties from the Diff or <seealso cref="ComparisonOptions.IncludeList"/> to only Diff properties contained in the list.</param>
        /// <returns></returns>
        public List <Difference> ComputeDiff <T>(T left, T right, int maxDepth, ComparisonOptions comparisonOptions, DiffOptions diffOptions, params Expression <Func <T, object> >[] propertiesToExcludeOrInclude)
        {
            var ignorePropertiesList = new List <string>();
            var expressionManager    = new ExpressionManager();

            if (propertiesToExcludeOrInclude != null)
            {
                foreach (var expression in propertiesToExcludeOrInclude)
                {
                    var name = expressionManager.GetPropertyPath(expression.Body);
                    ignorePropertiesList.Add(name);
                }
            }
            return(RecurseProperties(left, right, null, new List <Difference>(), 0, maxDepth, new ObjectHashcodeMap(), string.Empty, comparisonOptions, ignorePropertiesList, diffOptions));
        }
示例#6
0
        /// <summary>
        /// Compare two objects for value differences
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="left">Object A</param>
        /// <param name="right">Object B</param>
        /// <param name="comparisonOptions">Specify the comparison options</param>
        /// <param name="diffOptions">Specify custom diff options</param>
        /// <returns></returns>
        public static ICollection <Difference> Diff <T>(T left, T right, ComparisonOptions comparisonOptions, DiffOptions diffOptions)
        {
            var diffProvider = new DiffProvider();

            return(diffProvider.ComputeDiff(left, right, DiffProvider.DefaultMaxDepth, comparisonOptions, diffOptions));
        }
示例#7
0
        /// <summary>
        /// Compare two objects for value differences
        /// </summary>
        /// <param name="left">Object A</param>
        /// <param name="right">Object B</param>
        /// <param name="diffOptions">Specify custom diff options</param>
        /// <returns></returns>
        public static ICollection <Difference> Diff(object left, object right, DiffOptions diffOptions)
        {
            var diffProvider = new DiffProvider();

            return(diffProvider.ComputeDiff(left, right, DiffProvider.DefaultMaxDepth, ComparisonOptions.All, diffOptions));
        }
示例#8
0
        /// <summary>
        /// Compare two objects for value differences
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="left">Object A</param>
        /// <param name="right">Object B</param>
        /// <param name="maxDepth">Maximum recursion depth</param>
        /// <param name="comparisonOptions">Specify the comparison options</param>
        /// <param name="diffOptions">Specify custom diff options</param>
        /// <param name="propertiesToExcludeOrInclude">A list of property names or full path names to include/exclude. Default is <seealso cref="ComparisonOptions.ExcludeList"/>. Specify <seealso cref="ComparisonOptions.ExcludeList"/> to exclude the specified properties from the Diff or <seealso cref="ComparisonOptions.IncludeList"/> to only Diff properties contained in the list.</param>
        /// <returns></returns>
        public static ICollection <Difference> Diff <T>(T left, T right, int maxDepth, ComparisonOptions comparisonOptions, DiffOptions diffOptions, params Expression <Func <T, object> >[] propertiesToExcludeOrInclude)
        {
            var diffProvider = new DiffProvider();

            return(diffProvider.ComputeDiff(left, right, maxDepth, comparisonOptions, diffOptions, propertiesToExcludeOrInclude));
        }
示例#9
0
        /// <summary>
        /// Compare two objects for value differences
        /// </summary>
        /// <param name="left">Object A</param>
        /// <param name="right">Object B</param>
        /// <param name="maxDepth">Maximum recursion depth</param>
        /// <param name="comparisonOptions">Specify the comparison options</param>
        /// <param name="diffOptions">Specify custom diff options</param>
        /// <param name="propertiesToExcludeOrInclude">A list of property names or full path names to include/exclude. Default is <seealso cref="ComparisonOptions.ExcludeList"/>. Specify <seealso cref="ComparisonOptions.ExcludeList"/> to exclude the specified properties from the Diff or <seealso cref="ComparisonOptions.IncludeList"/> to only Diff properties contained in the list.</param>
        /// <returns></returns>
        public static ICollection <Difference> Diff(object left, object right, int maxDepth, ComparisonOptions comparisonOptions, DiffOptions diffOptions, params string[] propertiesToExcludeOrInclude)
        {
            var diffProvider = new DiffProvider();

            return(diffProvider.ComputeDiff(left, right, maxDepth, comparisonOptions, diffOptions, propertiesToExcludeOrInclude));
        }
示例#10
0
        /// <summary>
        /// Compare two objects for value differences
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="left">Object A</param>
        /// <param name="right">Object B</param>
        /// <param name="comparisonOptions">Specify the comparison options</param>
        /// <param name="diffOptions">Specify custom diff options</param>
        /// <param name="propertiesToExcludeOrInclude">A list of property names or full path names to include/exclude. Default is <seealso cref="ComparisonOptions.ExcludeList"/>. Specify <seealso cref="ComparisonOptions.ExcludeList"/> to exclude the specified properties from the Diff or <seealso cref="ComparisonOptions.IncludeList"/> to only Diff properties contained in the list.</param>
        /// <returns></returns>
        public static ICollection <Difference> Diff <T>(T left, T right, ComparisonOptions comparisonOptions, DiffOptions diffOptions, string[] propertiesToExcludeOrInclude)
        {
            var diffProvider = new DiffProvider();

            return(diffProvider.ComputeDiff(left, right, DiffProvider.DefaultMaxDepth, comparisonOptions, diffOptions, propertiesToExcludeOrInclude));
        }