注:如果出现列表类型,需要对数据先进行排序,否则位置不一样也会返回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;
}