关于比较对象,在"06判等对象是否相等"中大致可以总结为:
关于比较方法:
● 实例方法Equals(object
obj)既可以比较值类型,也可以比较引用类型
● 静态方法Equals(object objA, object objB),比较值类型
● 静态方法ReferenceEquals(object objA, object objB),比较引用类型
●
比较引用类型可以用==,比较值类型不能用==
关于比较原则:
● 值类型比较的是值
●
引用类型比较的是引用地址
对于复杂类型,无论是复杂值类型(比如结构)还是复杂引用类型(包含值类型成员),经常要重写System.Object中的虚方法Equals(object obj)。比如,针对复杂值类型,可能这样重写:
public override bool Equals(object obj)
{if (obj == null)
{return false;
}
RuntimeType type = (RuntimeType) base.GetType(); RuntimeType type2 = (RuntimeType) obj.GetType();
if (type2 != type) //比较两个对象是否是同一类型
{return false;
}
object a = this;
if (CanCompareBits(this)) //对象成员如果存在对于堆的引用返回false
{ return FastEqualsCheck(a, obj);}
//反射获取值类型的所有字段FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < fields.Length; i++) //遍历字段,对各个字段进行比较
{ object obj3 = ((RtFieldInfo) fields[i]).UnsafeGetValue(a); object obj4 = ((RtFieldInfo) fields[i]).UnsafeGetValue(obj);if (obj3 == null)
{if (obj4 != null)
{return false;
}
}
else if (!obj3.Equals(obj4))
{return false;
}
}
return true;
}
而现在,在NuGet上输入"Compare .NET objects",可以获取到该组件,对任何.NET对象进行比较、列出各个属性的值甚至自定义比较规则。
比较复杂类型:包含值类型成员
public class Teacher
{public int Id { get; set; }
public string Name { get; set; }
public DateTime JoinTime { get; set; } public TeacherClass TeacherClass { get; set; }}
public enum TeacherClass
{ [Description("执教5年以上")]FirstClass = 0,
[Description("执教3年以上")]SecondClass,
[Description("执教1年以上")]ThirdClass
}
主程序:
Teacher teacher1 = new Teacher(){Id=1,JoinTime = new DateTime(2014,1,1),Name = "张老师",TeacherClass = TeacherClass.FirstClass};
Teacher teacher2 = new Teacher() { Id = 2, JoinTime = new DateTime(2014, 1, 2), Name = "李老师", TeacherClass = TeacherClass.SecondClass };
//获取Teacher属性的个数int propertyCount = typeof (Teacher).GetProperties().Length;
//创建比较规则 CompareLogic compareLogic = new CompareLogic() { Config = new ComparisonConfig() { MaxDifferences = propertyCount//MaxDifferences的默认值是1}
};
bool result = compareLogic.Compare(teacher1, teacher2).AreEqual;Console.Write(result);
Console.ReadKey();
结果:false
比较复杂类型,并列出2个比较对象所有属性的值
Teacher teacher1 = new Teacher(){Id=1,JoinTime = new DateTime(2014,1,1),Name = "张老师",TeacherClass = TeacherClass.FirstClass};
Teacher teacher2 = new Teacher() { Id = 2, JoinTime = new DateTime(2014, 1, 2), Name = "李老师", TeacherClass = TeacherClass.SecondClass };
//获取Teacher属性的个数int propertyCount = typeof (Teacher).GetProperties().Length;
//创建比较规则 CompareLogic compareLogic = new CompareLogic() { Config = new ComparisonConfig() { MaxDifferences = propertyCount//MaxDifferences的默认值是1}
};
//获取2个比较对象的不同之处List<Difference> differences = compareLogic.Compare(teacher1, teacher2).Differences;
StringBuilder sb = new StringBuilder();foreach (Difference diff in differences)
{ sb.AppendLine("属性名称:" + diff.PropertyName); sb.AppendLine("第一个对象值:" + diff.Object1Value);sb.AppendLine("第二个对象值:" + diff.Object2Value + "\r\n");
}
using (StreamWriter outfile = new StreamWriter(@"F:\CompareObjects.txt"))
{outfile.Write(sb.ToString());
}
}
结果:
比较复杂类型,并列出2个比较对象所有属性的值,对枚举属性自定义比较规则
需要一个自定义类,继承"Compare .NET objects"的BaseTypeComparer类,把打在枚举成员上的描述特性信息输出。
重写方法IsTypeMatch()用于判断2个比较对象的属性是否是枚举,如果是枚举,就采用重写方法CompareType()所定义的关于枚举属性的比较规则。
public class CustomEnumComparer : BaseTypeComparer
{public CustomEnumComparer() : base(RootComparerFactory.GetRootComparer()){}
public override void CompareType(ComparisonResult result, object object1, object object2, string breadCrumb)
{ if (object1.ToString() != object2.ToString()) { Difference difference = new Difference() {PropertyName = breadCrumb,
Object1Value = EnumHelper.GetDescription(object1),
Object2Value = EnumHelper.GetDescription(object2),
Object1 = new WeakReference(object1), //弱对象引用,即使被引用也可被垃圾回收
Object2 = new WeakReference(object2)};
AddDifference(result,difference);
}
}
public override bool IsTypeMatch(Type type1, Type type2)
{ return TypeHelper.IsEnum(type1) && TypeHelper.IsEnum(type2);}
}
//获取枚举类型的描述特性public static class EnumHelper
{public static string GetDescription(object enumMember)
{ //获取枚举类型的字段信息FieldInfo fi = enumMember.GetType().GetField(enumMember.ToString());
//获取字段上的描述特性 IEnumerable<DescriptionAttribute> attributes = fi.GetCustomAttributes<DescriptionAttribute>(false); return attributes.Any() ? attributes.ElementAt(0).Description : enumMember.ToString();}
}
只需要把针对枚举属性的自定义类赋值给CompareLogic实例即可:
Teacher teacher1 = new Teacher(){Id=1,JoinTime = new DateTime(2014,1,1),Name = "张老师",TeacherClass = TeacherClass.FirstClass};
Teacher teacher2 = new Teacher() { Id = 2, JoinTime = new DateTime(2014, 1, 2), Name = "李老师", TeacherClass = TeacherClass.SecondClass };
//获取Teacher属性的个数int propertyCount = typeof (Teacher).GetProperties().Length;
//创建比较规则 CompareLogic compareLogic = new CompareLogic() { Config = new ComparisonConfig() { MaxDifferences = propertyCount,//MaxDifferences的默认值是1CustomComparers = new List<BaseTypeComparer>(){new CustomEnumComparer()}
}
};
//bool result = compareLogic.Compare(teacher1, teacher2).AreEqual; //Console.Write(result); //Console.ReadKey(); //获取2个比较对象的不同之处List<Difference> differences = compareLogic.Compare(teacher1, teacher2).Differences;
StringBuilder sb = new StringBuilder();foreach (Difference diff in differences)
{ sb.AppendLine("属性名称:" + diff.PropertyName); sb.AppendLine("第一个对象值:" + diff.Object1Value);sb.AppendLine("第二个对象值:" + diff.Object2Value + "\r\n");
}
using (StreamWriter outfile = new StreamWriter(@"F:\CompareObjects.txt"))
{outfile.Write(sb.ToString());
}
结果:
参考资料:
Compare .NET Objects Tutorial
26复杂类型比较,使用Compare .NET objects组件,布布扣,bubuko.com
26复杂类型比较,使用Compare .NET objects组件
原文:http://www.cnblogs.com/darrenji/p/3649646.html