private bool CompareMemberValues(ObjectComparisonData <T> data, Type memberType, object val1, object val2) { bool result = false; if (memberType == typeof(string) || memberType.IsValueType) { result = val1.Equals(val2); } else if (memberType.IsClass) { if (val1 != null && val2 != null) { // TODO: look up specific implementation for lists, collections, etc. if (memberType.GetInterfaces().Contains(typeof(IEnumerable))) { result = (val1 as IEnumerable).Count() == (val2 as IEnumerable).Count(); } else { result = ClassesHaveEqualValues(val1, val2, data, memberType); } } else { result = (val1 == null) && (val2 == null); } } return(result); }
public ObjectComparisonData(ObjectComparisonData <T> data) { VisitedObjectList1 = new List <long>(data.VisitedObjectList1); VisitedObjectList2 = new List <long>(data.VisitedObjectList2); ObjectIdGenerator1 = data.ObjectIdGenerator1; ObjectIdGenerator2 = data.ObjectIdGenerator2; WhereAmI = WhereAmI; }
private static void CheckForCircularReference(object obj1, object obj2, ObjectComparisonData <T> data) { var id1 = data.ObjectIdGenerator1.GetId(obj1, out bool firstTime1); var id2 = data.ObjectIdGenerator2.GetId(obj2, out bool firstTime2); if (data.VisitedObjectList1.Contains(id1) || data.VisitedObjectList2.Contains(id2)) { throw new ArgumentException("Circular reference"); } else { data.VisitedObjectList1.Add(id1); data.VisitedObjectList2.Add(id2); } }
private bool ClassesHaveEqualValues(object obj1, object obj2, ObjectComparisonData <T> data, Type memberType) { CheckForCircularReference(obj1, obj2, data); var members = GetPublicMembers(memberType); var enumerator = members.GetEnumerator(); var objectsEqual = true; while (objectsEqual && enumerator.MoveNext()) { var member = (MemberInfo)enumerator.Current; var propertyType = member.GetUnderlyingType(); var val1 = member.GetValue(obj1); var val2 = member.GetValue(obj2); // Append the current member to the current expression to form a new expression. var currentPropertyExpression = Expression.PropertyOrField(data.WhereAmI, member.Name); // TODO: Collections are not implemented yet. // Rules for specific properties take precedence over rules for types. if (this._equalityFunctionByExpression.TryGetValue(GetExpressionString(currentPropertyExpression), out Func <object, object, bool> func1)) { objectsEqual = func1(val1, val2); } else if (_typeOverrides.TryGetValue(propertyType, out Func <object, object, bool> func2)) { objectsEqual = func2(val1, val2); } else { var objData = new ObjectComparisonData <T>(data) { WhereAmI = currentPropertyExpression }; objectsEqual = CompareMemberValues(objData, propertyType, val1, val2); } } return(objectsEqual); }