private ComparisonRule GetComparisonRuleOrNull(Type type1, Type type2, string type1PropertyName, string type2PropertyName) { ComparisonRule comparisonRule = this.comparisonRules?.SingleOrDefault(rule => rule.Type1 == type1 && rule.Type2 == type2 && rule.Type1PropertyName == type1PropertyName && rule.Type2PropertyName == type2PropertyName) ?? this.comparisonRules?.SingleOrDefault(rule => rule.Type2 == type1 && rule.Type1 == type2 && rule.Type2PropertyName == type1PropertyName && rule.Type1PropertyName == type2PropertyName)?.Flip(); return(comparisonRule); }
/// <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); }