unity 判断两个相同引用类型对象的属性值是否完全相同

注:如果出现列表类型,需要对数据先进行排序,否则位置不一样也会返回false

/// <summary>
        /// 判断两个相同引用类型的对象的属性值是否相等
        /// 比较前需要对两个对象的属性值进行排序
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj1">对象1:上一个对象</param>
        /// <param name="obj2">对象2:当前对象</param>
        /// <param name="type">按type类型中的属性进行比较</param>
        /// <returns></returns>
        public static bool ComparePropertiesValueSame<T>(T obj1, T obj2, Type type)
        {
    
    
            if (type == null)
            {
    
    
                return false;
            }
            bool isSame = true;//是否完全一致

            DescriptionAttribute descriptionAttr = type.GetCustomAttribute<DescriptionAttribute>();
            string descriptionName = descriptionAttr?.Description;

            //为空判断
            if (obj1 == null && obj2 == null)
            {
    
    
                return true;
            }
            else if (obj1 == null && obj2 != null)
            {
    
    
                return false;
            }
            else if (obj1 != null && obj2 == null)
            {
    
    
                return false;
            }
            else if (IsCanCompare(type))
            {
    
    
                if (!obj1.Equals(obj2))
                {
    
    
                    return false;
                }
                return true;
            }
            else if (typeof(IList).IsAssignableFrom(type))
            {
    
    
                //当前属性类型是否继承于【列表】IList,List<T>和Array都继承于IList
                IList tempObj1 = obj1 as IList;//此时obj1,obj2一定不为null
                IList tempObj2 = obj2 as IList;
                if (tempObj1.Count != tempObj2.Count)
                {
    
    
                    return false;
                }
                //集合格式一致,就遍历每一个元素
                for (int i = 0; i < tempObj1.Count; i++)
                {
    
    
                    bool isSameTemp = ComparePropertiesValueSame(tempObj1[i], tempObj2[i], tempObj1[i].GetType());
                    if (!isSameTemp)
                    {
    
    
                        isSame = false;//如果存在某一个属性值被更新,就认为是更新了
                    }
                }
                return isSame;
            }
            else if (typeof(IDictionary).IsAssignableFrom(type))
            {
    
    
                //当前属性类型是否继承于【键值对字典】IDictionary,Dcitionary和Hashtable都继承于IDictionary
                IDictionary tempObj1 = obj1 as IDictionary;//此时obj1,obj2一定不为null
                IDictionary tempObj2 = obj2 as IDictionary;
                if (tempObj1.Count != tempObj2.Count)
                {
    
    
                    return false;
                }
                //集合格式一致,就遍历每一个元素
                IDictionaryEnumerator enu1 = tempObj1.GetEnumerator();
                IDictionaryEnumerator enu2 = tempObj2.GetEnumerator();
                //集合格式一致,就遍历每一个元素
                for (int i = 0; i < tempObj1.Count; i++)
                {
    
    
                    enu1.MoveNext();
                    enu2.MoveNext();
                    bool isSameTempKey = ComparePropertiesValueSame(enu1.Key, enu2.Key, enu1.Key.GetType());
                    bool isSameTempValue = ComparePropertiesValueSame(enu1.Value, enu2.Value, enu1.Value.GetType());
                    if (!isSameTempKey || !isSameTempValue)
                    {
    
    
                        isSame = false;//如果存在某一个属性值被更新,就认为是更新了
                    }
                }
                return isSame;
            }
            else if (typeof(IEnumerable).IsAssignableFrom(type)) //对集合进行特殊处理
            {
    
    
                //当前属性类型是否继承于【枚举数集合】IEnumerable,HashSet、Queue和Stack都继承于IEnumerable
                IEnumerable tempObj1 = obj1 as IEnumerable;//此时obj1,obj2一定不为null
                IEnumerable tempObj2 = obj2 as IEnumerable;
                //集合格式一致,就遍历每一个元素
                IEnumerator enu1 = tempObj1.GetEnumerator();
                IEnumerator enu2 = tempObj2.GetEnumerator();
                //集合格式一致,就遍历每一个元素
                while (enu1.MoveNext() && enu2.MoveNext())
                {
    
    
                    bool isSameTemp = ComparePropertiesValueSame(enu1.Current, enu2.Current, enu1.Current.GetType());
                    if (!isSameTemp)
                    {
    
    
                        isSame = false;//如果存在某一个属性值被更新,就认为是更新了
                    }
                }
                //如果结尾的时候,某一个集合仍然有值,说明集合个数不一致
                if (enu1.MoveNext() || enu2.MoveNext())
                {
    
    
                    return false;
                }
                return isSame;
            }
            //如果是自定义类CustomClass
            //遍历出当前类型的所有公共字段 和 公共属性
            MemberInfo[] memberInfos = type.GetMembers();
            foreach (MemberInfo po in memberInfos)
            {
    
    
                if (po.MemberType != MemberTypes.Field && po.MemberType != MemberTypes.Property)
                {
    
    
                    //只考虑字段和属性,不考虑构造函数、方法、事件等
                    continue;
                }
                object oldVal = null;
                object newVal = null;
                Type objType = null;
                if (po is PropertyInfo pi)
                {
    
    
                    objType = pi.PropertyType;//属性类型
                    oldVal = pi.GetValue(obj1);//旧值
                    newVal = pi.GetValue(obj2);//新值 
                }
                else if (po is FieldInfo fi)
                {
    
    
                    objType = fi.FieldType;//字段类型
                    oldVal = fi.GetValue(obj1);//旧值
                    newVal = fi.GetValue(obj2);//新值 
                }
                DescriptionAttribute descriptionAttribute = po.GetCustomAttribute<DescriptionAttribute>(false);
                if (oldVal == null && newVal == null)
                {
    
    
                    //仍是相等 初始值都为null
                    continue;
                }
                bool isSameTemp = ComparePropertiesValueSame(oldVal, newVal, objType);
                if (!isSameTemp)
                {
    
    
                    isSame = false;//如果存在某一个属性值被更新,就认为是更新了
                }
            }
            return isSame;
        }

        /// <summary>
        /// 该类型是否可直接进行值的比较
        /// 所有的结构Struct【比如int,double,DateTime】,枚举Enum 都是值类型,字符串也是可以比较的
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        private static bool IsCanCompare(Type t)
        {
    
    
            //所有的结构Struct【比如int,double,DateTime】,枚举Enum 都是值类型
            if (t.IsValueType)
            {
    
    
                return true;
            }
            if (t.FullName == typeof(string).FullName)
            {
    
    
                return true;
            }
            return false;
        }

猜你喜欢

转载自blog.csdn.net/weixin_47819574/article/details/131292414