Example #1
0
        private CheckEqualityResult CompareEnumerables(IEnumerable enumerable1, IEnumerable enumerable2)
        {
            //Order doesn't matter but should be preserved
            List <object> list1 = enumerable1.Cast <object>().ToList();
            List <object> list2 = enumerable2.Cast <object>().ToList();

            if (list2.Count != list1.Count)
            {
                return(CheckEqualityResult.False("Collection counts do not match"));
            }
            var checkResult = list1.Select((item1, i) => this.CheckEquality(item1, list2[i])).FirstOrDefault(check => !check.Equal);

            return(checkResult != null ? checkResult : CheckEqualityResult.True);
        }
        private CheckEqualityResult CompareEnumerables(IEnumerable enumerable1, IEnumerable enumerable2)
        {
            //Order doesn't matter but should be preserved
            List <object> list1 = enumerable1.Cast <object>().ToList();
            List <object> list2 = enumerable2.Cast <object>().ToList();

            if (list2.Count != list1.Count)
            {
                return(CheckEqualityResult.False("Collection counts do not match"));
            }

            bool anyFailures = list1.Select((item1, i) => this.CheckEquality(item1, list2[i])).Any(s => !s.Equal);

            return(anyFailures ? CheckEqualityResult.False("Collection mismatch") : CheckEqualityResult.True);
        }
        public CheckEqualityResult CheckEquality(object o1, object o2)
        {
            if (o1 == null && o2 == null)
            {
                return(CheckEqualityResult.True);
            }
            else if (o1 == null && o2 != null)
            {
                return(CheckEqualityResult.False("o1 == null but not o2"));
            }
            else if (o1 != null && o2 == null)
            {
                return(CheckEqualityResult.False("o2 == null but not o1"));
            }

            Type o1Type = o1.GetType();
            Type o2Type = o2.GetType();

            if (o1 is Enum && o2 is Enum)
            {
                //Match enums based on an ignore-cased ToString
                bool matches = o1.ToString().Equals(o2.ToString(), StringComparison.CurrentCultureIgnoreCase);
                if (matches)
                {
                    return(CheckEqualityResult.True);
                }
                else
                {
                    return(CheckEqualityResult.False(string.Format("Enum {0} doesn't match {1}", o1, o2)));
                }
            }
            //Check to see if the object is using "System.Object"'s default comparator
            else if (OverridesEqualsMethod(o1Type))
            {
                //Since we are not using System.Objects default equals implementation we can go ahead
                //and just call .Equals
                if (o1.Equals(o2))
                {
                    return(CheckEqualityResult.True);
                }
                else
                {
                    return(CheckEqualityResult.False(string.Format("Type {0}.Equals({1}) returned false", o1Type, o2Type)));
                }
            }
            //Deal with collections
            else if (o1 is IEnumerable)
            {
                if (!(o2 is IEnumerable))
                {
                    return(CheckEqualityResult.False("o2 was not IEnumerable"));
                }

                IEnumerable o1Enumerable = (IEnumerable)o1;
                IEnumerable o2Enumerable = (IEnumerable)o2;

                return(this.CompareEnumerables(o1Enumerable, o2Enumerable));
            }
            else
            {
                return(this.DoesComplexTypeOneMatchTypeTwo(o1, o2));
            }
        }
        /// <summary>
        /// Compares the two types, ensuring that all properties of <paramref name="o2"/> are matched by corresponding properties of <paramref name="o1"/>.
        /// </summary>
        private CheckEqualityResult DoesComplexTypeOneMatchTypeTwo(object o1, object o2)
        {
            Type o1Type = o1.GetType();
            Type o2Type = o2.GetType();

            PropertyInfo[] o1Properties = o1Type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
            PropertyInfo[] o2Properties = o2Type.GetProperties(BindingFlags.Instance | BindingFlags.Public);

            List <string> o1PropertyNames = o1Properties.Select(prop => prop.Name).ToList();

            foreach (PropertyInfo o2Property in o2Properties)
            {
                object o2Value        = o2Property.GetValue(o2);
                string o1PropertyName = o2Property.Name;

                //Find the corresponding o1 property if there is one
                if (!o1PropertyNames.Contains(o2Property.Name))
                {
                    string mappedPropertyName = this.GetPropertyMappingOrNull(o2Type, o2Property.Name);
                    if (!string.IsNullOrEmpty(mappedPropertyName))
                    {
                        //Property names don't match but we have a mapping which maps them
                        o1PropertyName = mappedPropertyName;
                    }
                    else
                    {
                        return(CheckEqualityResult.False(string.Format("Unknown property: {0} on type {1}", o2Property.Name, o2Type)));
                    }
                }

                PropertyInfo o1Property = o1Type.GetProperty(o1PropertyName);

                try
                {
                    object o1Value = o1Property.GetValue(o1);

                    ComparisonRule customComparisonRule = this.GetComparisonRuleOrNull(o1Type, o2Type, o1PropertyName, o2Property.Name);

                    if (customComparisonRule != null)
                    {
                        CheckEqualityResult result = customComparisonRule.Comparer(o1Value, o2Value);
                        if (!result.Equal)
                        {
                            return(result);
                        }
                    }
                    else
                    {
                        CheckEqualityResult result = this.CheckEquality(o1Value, o2Value);
                        if (!result.Equal)
                        {
                            return(result);
                        }
                    }
                }
                catch (TargetInvocationException e)
                {
                    if (this.shouldSwallowPropertyReadException(e))
                    {
                        throw;
                    }
                }
            }

            return(CheckEqualityResult.True);
        }