C#与可忽略列表相等
我有一些具有许多简单属性的类(来自我无法控制的数据模型)——我希望能够找到对象的新版本是否与旧版本相同,但不想使用20种不同的“IsEqual”方法(我不太喜欢“IsEqual”名称,因为它不是与==”的类比)。另一个问题,在大多数情况下,我不希望它做深入的比较,但在某些情况下,我确实希望这样 我想要一些大致如下的东西:C#与可忽略列表相等,c#,generics,compare,C#,Generics,Compare,我有一些具有许多简单属性的类(来自我无法控制的数据模型)——我希望能够找到对象的新版本是否与旧版本相同,但不想使用20种不同的“IsEqual”方法(我不太喜欢“IsEqual”名称,因为它不是与==”的类比)。另一个问题,在大多数情况下,我不希望它做深入的比较,但在某些情况下,我确实希望这样 我想要一些大致如下的东西: //Property could be PropertyInfo if that is necessary bool IsEqual<T>(T first, T s
//Property could be PropertyInfo if that is necessary
bool IsEqual<T>(T first, T second, List<Property> ignorableProperties=emptyList, bool recurse=false)
{
//the comparison code returning if they are equal ignoring
//the properties in the ignorableProperties list, recursing if recurse == true
//not sure how I'd handle the comparison of sub-objects in the recursive step.
}
//如果需要,属性可以是PropertyInfo
bool IsEqual(T first,T second,List ignorableProperties=emptyList,bool recurse=false)
{
//如果它们相等,则返回比较代码
//ignorableProperties列表中的属性,如果recurse==true则递归
//不确定在递归步骤中如何处理子对象的比较。
}
下面是我们代码库中的一些内容。它使用要比较的属性列表,而不是要忽略的属性列表。然后返回属性不匹配的列表:
public static List<PropertyInfo> CompareObjects<T>(T o1, T o2, List<PropertyInfo> props) where T : class
{
var type = typeof(T);
var mismatched = CompareObjects(type, o1, o2, props);
return mismatched;
}
public static List<PropertyInfo> CompareObjects(Type t, object o1, object o2, List<PropertyInfo> props)
{
List<PropertyInfo> mismatched = null;
foreach (PropertyInfo prop in props)
{
if (prop.GetValue(o1, null) == null && prop.GetValue(o2, null) == null) ;
else if (
prop.GetValue(o1, null) == null || prop.GetValue(o2, null) == null ||
!prop.GetValue(o1, null).Equals(prop.GetValue(o2, null)))
{
if (mismatched == null) mismatched = new List<PropertyInfo>();
mismatched.Add(prop);
}
}
return mismatched;
}
公共静态列表比较对象(to1,to2,List props),其中T:class
{
var类型=类型(T);
var不匹配=比较对象(类型、o1、o2、道具);
收益不匹配;
}
公共静态列表比较对象(类型t、对象o1、对象o2、列表道具)
{
列表不匹配=空;
foreach(PropertyInfo props in props)
{
if(prop.GetValue(o1,null)==null&&prop.GetValue(o2,null)==null);
否则如果(
prop.GetValue(o1,null)==null | | prop.GetValue(o2,null)==null||
!prop.GetValue(o1,null).等于(prop.GetValue(o2,null)))
{
if(mismatched==null)mismatched=new List();
不匹配。添加(道具);
}
}
收益不匹配;
}
如果您想要一个IsEqual方法,那么当您发现不匹配的属性时,只需返回true
/false
希望这有帮助 下面是我们代码库中的一些内容。它使用要比较的属性列表,而不是要忽略的属性列表。然后返回属性不匹配的列表:
public static List<PropertyInfo> CompareObjects<T>(T o1, T o2, List<PropertyInfo> props) where T : class
{
var type = typeof(T);
var mismatched = CompareObjects(type, o1, o2, props);
return mismatched;
}
public static List<PropertyInfo> CompareObjects(Type t, object o1, object o2, List<PropertyInfo> props)
{
List<PropertyInfo> mismatched = null;
foreach (PropertyInfo prop in props)
{
if (prop.GetValue(o1, null) == null && prop.GetValue(o2, null) == null) ;
else if (
prop.GetValue(o1, null) == null || prop.GetValue(o2, null) == null ||
!prop.GetValue(o1, null).Equals(prop.GetValue(o2, null)))
{
if (mismatched == null) mismatched = new List<PropertyInfo>();
mismatched.Add(prop);
}
}
return mismatched;
}
public static bool AreEqual<T>(this T first, T second,
bool recurse = false, params string[] propertiesToSkip)
{
if (Equals(first, second)) return true;
if (first == null)
return second == null;
else if (second == null)
return false;
if (propertiesToSkip == null) propertiesToSkip = new string[] { };
var properties = from t in first.GetType().GetProperties()
where t.CanRead
select t;
foreach (var property in properties)
{
if (propertiesToSkip.Contains(property.Name)) continue;
var v1 = property.GetValue(first, null);
var v2 = property.GetValue(second, null);
if (recurse)
if (!AreEqual(v1, v2, true, propertiesToSkip))
return false;
else
continue;
if (!Equals(v1, v2)) return false;
}
return true;
}
公共静态列表比较对象(to1,to2,List props),其中T:class
{
var类型=类型(T);
var不匹配=比较对象(类型、o1、o2、道具);
收益不匹配;
}
公共静态列表比较对象(类型t、对象o1、对象o2、列表道具)
{
列表不匹配=空;
foreach(PropertyInfo props in props)
{
if(prop.GetValue(o1,null)==null&&prop.GetValue(o2,null)==null);
否则如果(
prop.GetValue(o1,null)==null | | prop.GetValue(o2,null)==null||
!prop.GetValue(o1,null).等于(prop.GetValue(o2,null)))
{
if(mismatched==null)mismatched=new List();
不匹配。添加(道具);
}
}
收益不匹配;
}
如果您想要一个IsEqual方法,那么当您发现不匹配的属性时,只需返回true
/false
希望这有帮助 public static bool是相等的(这是T-first,T-second,
public static bool AreEqual<T>(this T first, T second,
bool recurse = false, params string[] propertiesToSkip)
{
if (Equals(first, second)) return true;
if (first == null)
return second == null;
else if (second == null)
return false;
if (propertiesToSkip == null) propertiesToSkip = new string[] { };
var properties = from t in first.GetType().GetProperties()
where t.CanRead
select t;
foreach (var property in properties)
{
if (propertiesToSkip.Contains(property.Name)) continue;
var v1 = property.GetValue(first, null);
var v2 = property.GetValue(second, null);
if (recurse)
if (!AreEqual(v1, v2, true, propertiesToSkip))
return false;
else
continue;
if (!Equals(v1, v2)) return false;
}
return true;
}
bool recurse=false,参数字符串[]属性跳过)
{
if(Equals(first,second))返回true;
if(first==null)
返回second==null;
else if(秒==null)
返回false;
如果(propertiesToSkip==null)propertiesToSkip=新字符串[]{};
var properties=first.GetType().GetProperties()中的t
t.CanRead在哪里
选择t;
foreach(属性中的var属性)
{
如果(propertiesToSkip.Contains(property.Name))继续;
var v1=property.GetValue(第一个,null);
var v2=property.GetValue(第二个,null);
if(递归)
如果(!AreEqual(v1、v2、true、propertiesToSkip))
返回false;
其他的
继续;
如果(!Equals(v1,v2))返回false;
}
返回true;
}
公共静态布尔值相等(第一个T,第二个T,
bool recurse=false,参数字符串[]属性跳过)
{
if(Equals(first,second))返回true;
if(first==null)
返回second==null;
else if(秒==null)
返回false;
如果(propertiesToSkip==null)propertiesToSkip=新字符串[]{};
var properties=first.GetType().GetProperties()中的t
t.CanRead在哪里
选择t;
foreach(属性中的var属性)
{
如果(propertiesToSkip.Contains(property.Name))继续;
var v1=property.GetValue(第一个,null);
var v2=property.GetValue(第二个,null);
if(递归)
如果(!AreEqual(v1、v2、true、propertiesToSkip))
返回false;
其他的
继续;
如果(!Equals(v1,v2))返回false;
}
返回true;
}
以下是我们如何在Umbraco框架中实现这一点的,该框架使用了一个名为AbstractEquatableObject的基类,它是Sharp Architecture的BaseObject的一个修改版本
实现者重写GetMembersForEqualityComparison()
,基类在ConcurrentDictionary
中为应用程序的每种类型缓存PropertyInfo对象一次
我已经在这里粘贴了这个类,尽管它引用了框架中其他地方的LogHelper,所以您可以删除它(或者只使用我们的框架库,里面还有其他有用的东西)
如果您想要一个从表达式获取PropertyInfo的助手,为了避免到处都是神奇的字符串(例如,替换为x=>x.MyProperty
),请查看ExpressionHelper的GetPropertyInfo方法,网址为
使用系统;
使用System.Collections.Concurrent;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
使用Umbraco.Framework.Diagnostics;
命名空间Umbraco.Framework
{
///
///为实现的对象提供了用于建立特定于域的相等性的通用功能
///以及一个健壮的GetHa实现