/// <summary> /// Compare the properties of a class /// </summary> /// <param name="t1"></param> /// <param name="object1"></param> /// <param name="object2"></param> /// <param name="breadCrumb"></param> private void PerformCompareProperties(Type t1, object object1, object object2, string breadCrumb) { IEnumerable <PropertyInfo> currentProperties = GetPropertyInfo(t1); foreach (PropertyInfo info in currentProperties) { //If we can't read it, skip it if (info.CanRead == false) { continue; } //Skip if this is a shallow compare if (!CompareChildren && IsChildType(info.PropertyType)) { continue; } //If we should ignore it, skip it if (ElementsToIgnore.Contains(info.Name) || IgnoredByAttribute(info.PropertyType)) { continue; } //If we should ignore read only, skip it if (!CompareReadOnly && info.CanWrite == false) { continue; } object objectValue1; object objectValue2; if (!IsValidIndexer(info, breadCrumb)) { objectValue1 = info.GetValue(object1, null); objectValue2 = info.GetValue(object2, null); } else { CompareIndexer(info, object1, object2, breadCrumb); continue; } bool object1IsParent = objectValue1 != null && (objectValue1 == object1 || _parents.Contains(objectValue1)); bool object2IsParent = objectValue2 != null && (objectValue2 == object2 || _parents.Contains(objectValue2)); //Skip properties where both point to the corresponding parent if ((IsClass(info.PropertyType) || IsStruct(info.PropertyType)) && (object1IsParent && object2IsParent)) { continue; } string currentCrumb = AddBreadCrumb(breadCrumb, info.Name, string.Empty, -1); Compare(objectValue1, objectValue2, currentCrumb); if (Differences.Count >= MaxDifferences) { return; } } }
/// <summary> /// Compare the properties of a class /// </summary> /// <param name="t1"></param> /// <param name="object1"></param> /// <param name="object2"></param> /// <param name="breadCrumb"></param> private void PerformCompareProperties(Type t1, object object1, object object2, string breadCrumb) { object objectValue1; object objectValue2; string currentCrumb; PropertyInfo[] currentProperties; if (ComparePrivateProperties) { currentProperties = t1.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); } else { currentProperties = t1.GetProperties(); //Default is public instance } foreach (var info in currentProperties) { //If we can't read it, skip it if (info.CanRead == false) { continue; } //Skip if this is a shallow compare if (!CompareChildren && IsChildType(info.PropertyType)) { continue; } //If we should ignore it, skip it if (ElementsToIgnore.Contains(info.Name)) { continue; } //If we should ignore read only, skip it if (!CompareReadOnly && info.CanWrite == false) { continue; } if (!IsValidIndexer(info, object1, object2, breadCrumb)) { objectValue1 = info.GetValue(object1, null); objectValue2 = info.GetValue(object2, null); } else { CompareIndexer(info, object1, object2, breadCrumb); continue; ; } bool object1IsParent = objectValue1 != null && (objectValue1 == object1 || _parents.Contains(objectValue1)); bool object2IsParent = objectValue2 != null && (objectValue2 == object2 || _parents.Contains(objectValue2)); //Skip properties where both point to the corresponding parent if (IsClass(info.PropertyType) && (object1IsParent && object2IsParent)) { continue; } currentCrumb = AddBreadCrumb(breadCrumb, info.Name, string.Empty, -1); Compare(objectValue1, objectValue2, currentCrumb); if (Differences.Count >= MaxDifferences) { return; } } }
private void CompareDataRow(object object1, object object2, string breadCrumb) { var dataRow1 = object1 as DataRow; var dataRow2 = object2 as DataRow; if (dataRow1 == null) //This should never happen, null check happens one level up { throw new ArgumentNullException("object1"); } if (dataRow2 == null) //This should never happen, null check happens one level up { throw new ArgumentNullException("object2"); } for (int i = 0; i < dataRow1.Table.Columns.Count; i++) { //If we should ignore it, skip it if (ElementsToIgnore.Contains(dataRow1.Table.Columns[i].ColumnName)) { continue; } //If we should ignore read only, skip it if (!CompareReadOnly && dataRow1.Table.Columns[i].ReadOnly) { continue; } //Both are null if (dataRow1.IsNull(i) && dataRow2.IsNull(i)) { continue; } string currentBreadCrumb = AddBreadCrumb(breadCrumb, string.Empty, string.Empty, dataRow1.Table.Columns[i].ColumnName); //Check if one of them is null if (dataRow1.IsNull(i)) { Differences.Add(string.Format("object1{0} == null && object2{0} != null ((null),{1})", currentBreadCrumb, cStr(object2))); return; } if (dataRow2.IsNull(i)) { Differences.Add(string.Format("object1{0} != null && object2{0} == null ({1},(null))", currentBreadCrumb, cStr(object1))); return; } Compare(dataRow1[i], dataRow2[i], currentBreadCrumb); if (Differences.Count >= MaxDifferences) { return; } } }
private void CompareDataTable(object object1, object object2, string breadCrumb) { var dataTable1 = object1 as DataTable; var dataTable2 = object2 as DataTable; if (dataTable1 == null) //This should never happen, null check happens one level up { throw new ArgumentNullException("object1"); } if (dataTable2 == null) //This should never happen, null check happens one level up { throw new ArgumentNullException("object2"); } //If we should ignore it, skip it if (ElementsToIgnore.Contains(dataTable1.TableName)) { return; } //There must be the same amount of rows in the datatable if (dataTable1.Rows.Count != dataTable2.Rows.Count) { Differences.Add(string.Format("object1{0}.Rows.Count != object2{0}.Rows.Count ({1},{2})", breadCrumb, dataTable1.Rows.Count, dataTable2.Rows.Count)); if (Differences.Count >= MaxDifferences) { return; } } //There must be the same amount of columns in the datatable if (dataTable1.Columns.Count != dataTable2.Columns.Count) { Differences.Add(string.Format("object1{0}.Columns.Count != object2{0}.Columns.Count ({1},{2})", breadCrumb, dataTable1.Columns.Count, dataTable2.Columns.Count)); if (Differences.Count >= MaxDifferences) { return; } } for (int i = 0; i < dataTable1.Rows.Count; i++) { string currentBreadCrumb = AddBreadCrumb(breadCrumb, "Rows", string.Empty, i); CompareDataRow(dataTable1.Rows[i], dataTable2.Rows[i], currentBreadCrumb); if (Differences.Count >= MaxDifferences) { return; } } }
/// <summary> /// Compare the properties of a class /// </summary> /// <param name="t1"></param> /// <param name="object1"></param> /// <param name="object2"></param> /// <param name="breadCrumb"></param> private void PerformCompareProperties(Type t1, object object1, object object2, bool structCompare, string breadCrumb) { IEnumerable <PropertyInfo> currentProperties = GetPropertyInfo(t1); foreach (PropertyInfo info in currentProperties) { //Ignore invalid struct fields if (structCompare && !ValidStructSubType(info.PropertyType)) { continue; } //If we can't read it, skip it if (info.CanRead == false) { continue; } //Skip if this is a shallow compare if (!CompareChildren && IsChildType(info.PropertyType)) { continue; } //If we should ignore it, skip it if (ElementsToIgnore.Contains(info.Name) || IgnoredByAttribute(info.PropertyType) || // November 25, 2012 // Added the ability to // ignore by attributes on // fields/properties. IgnoredByAttribute(info.GetCustomAttributes(true))) { continue; } //If we should ignore read only, skip it if (!CompareReadOnly && info.CanWrite == false) { continue; } //If we ignore types then we must get correct PropertyInfo object PropertyInfo secondObjectInfo = null; if (IgnoreObjectTypes) { var secondObjectPropertyInfos = GetPropertyInfo(object2.GetType()); foreach (var propertyInfo in secondObjectPropertyInfos) { if (propertyInfo.Name != info.Name) { continue; } secondObjectInfo = propertyInfo; break; } } else { secondObjectInfo = info; } object objectValue1; object objectValue2; if (!IsValidIndexer(info, breadCrumb)) { objectValue1 = info.GetValue(object1, null); objectValue2 = secondObjectInfo != null?secondObjectInfo.GetValue(object2, null) : null; } else { CompareIndexer(info, object1, object2, breadCrumb); continue; } bool object1IsParent = objectValue1 != null && (objectValue1 == object1 || _parents.Contains(objectValue1)); bool object2IsParent = objectValue2 != null && (objectValue2 == object2 || _parents.Contains(objectValue2)); //Skip properties where both point to the corresponding parent if ((IsClass(info.PropertyType) || IsStruct(info.PropertyType)) && (object1IsParent && object2IsParent)) { continue; } string currentCrumb = AddBreadCrumb(breadCrumb, info.Name, string.Empty, -1); Compare(objectValue1, objectValue2, currentCrumb); if (Differences.Count >= MaxDifferences) { return; } } }