zoukankan      html  css  js  c++  java
  • 26复杂类型比较,使用Compare .NET objects组件

    关于比较对象,在"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对象进行比较、列出各个属性的值甚至自定义比较规则。

    1

     

      比较复杂类型:包含值类型成员

        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 + "
    ");
                }
     
                using (StreamWriter outfile = new StreamWriter(@"F:CompareObjects.txt"))
                {
                    outfile.Write(sb.ToString());
                }
            }  

    结果:

    3

     

      比较复杂类型,并列出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的默认值是1
                        CustomComparers = 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 + "
    ");
                }
     
                using (StreamWriter outfile = new StreamWriter(@"F:CompareObjects.txt"))
                {
                    outfile.Write(sb.ToString());
                }

    结果:

    2

     

    参考资料:
    Compare .NET Objects Tutorial

  • 相关阅读:
    java回调函数这样说,应该明确了吧!
    Aamazon Web Service EC2 Ubuntu 新建用户而且用ssh连接host
    Html animation by css(Sequence Js Tutorial)
    shell脚本一键安装mysql5.7.x
    HDU 4544 湫湫系列故事――消灭兔子
    简明python教程 --C++程序员的视角(八):标准库
    简明python教程 --C++程序员的视角(七):异常
    简明python教程 --C++程序员的视角(六):输入输出IO
    简明python教程 --C++程序员的视角(五):面向对象的编程
    简明python教程 --C++程序员的视角(四):容器类型(字符串、元组、列表、字典)和参考
  • 原文地址:https://www.cnblogs.com/darrenji/p/3649646.html
Copyright © 2011-2022 走看看