以this答案为基础,用于比较C#中的对象 Comparing object properties in c#
知道这是一个复杂的主题,我想处理一些更具体的结构。
如果这些代码是简单的值类型,例如此对象,则此代码将匹配属性:
public class BasicStuff
{
public int anInt { get; set; }
public bool aBool { get; set; }
}
但是一旦它变得更复杂,这段代码就会失败。
所以我想做的是让它对上面的嵌套对象更有用,例如:
public class NestedStuff
{
public BasicStuff theBasic { get; set; }
}
以上任何数组,例如:
public class ArrayStuff
{
public BasicStuff[] theBasicArray { get; set; }
}
最后是上述的任何组合:
public class AllTheStuff
{
public int anInt { get; set; }
public bool aBool { get; set; }
public BasicStuff theBasic { get; set; }
public BasicStuff[] theBasicArray { get; set; }
}
所以我想出的是以下内容:
public static bool AllPublicPropertiesEqual<T>(T AObj, T BObj, params string[] ignore) where T : class
{
if (AObj != null && BObj != null)
{
Type type = typeof(T);
List<string> ignoreList = new List<string>(ignore);
foreach (PropertyInfo pInfo in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (!ignoreList.Contains(pInfo.Name))
{
if (pInfo.PropertyType.IsArray)
{
object AValue = type.GetProperty(pInfo.Name).GetValue(AObj, null);
object BValue = type.GetProperty(pInfo.Name).GetValue(BObj, null);
string t = AValue.GetType().ToString();
if (!AllPublicPropertiesEqual<object>(AValue, BValue))
return false;
}
else if (!pInfo.PropertyType.IsValueType && !pInfo.PropertyType.IsPrimitive && !pInfo.PropertyType.IsEnum && pInfo.PropertyType != typeof(string))
//else if (Convert.GetTypeCode(pInfo.PropertyType) == TypeCode.Object)
{
object AValue = type.GetProperty(pInfo.Name).GetValue(AObj, null);
object BValue = type.GetProperty(pInfo.Name).GetValue(BObj, null);
if (!AllPublicPropertiesEqual<object>(BValue, AValue))
return false;
}
else
{
object selfValue = type.GetProperty(pInfo.Name).GetValue(AObj, null);
object toValue = type.GetProperty(pInfo.Name).GetValue(BObj, null);
if (selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue)))
return false;
}
}
}
return true;
}
return AObj == BObj;
}
只有这会失败,因为在递归调用AllPublicPropertiesEqual时,我需要传递特定的值类型而不仅仅是通用对象类型。 但我不知道该怎么做......任何想法都非常感谢...
答案 0 :(得分:0)
您的方法不必是通用的。您可以将方法的开头更改为:
public static bool AllPublicPropertiesEqual(object AObj, object BObj, params string[] ignore)
{
if (AObj != null && BObj != null)
{
Type type = AObj.GetType();
if (BObj.GetType() != type)
throw new Exception("Objects should be of the same type");
....
}
....
}
答案 1 :(得分:0)
首先,你应该为这些类创建接口,因为从我看到你可以组合这些类,但所有类都具有相同的属性。第二个选项是使用这些属性创建一些Base抽象类并从中继承。这取决于你选择的是什么。 比在这个Base类或Interface Equals函数中创建,你将直接等于共享属性,它更容易,我觉得更有效: - )
public abstract class BaseStaff {
public int anInt { get; set; }
public bool aBool { get; set; }
public abstract bool Equals(BaseStaff anotherStaff);
}
然后你可以使用这个类在BasicStaff中创建你的BasicStaff类和AllTheStaff类,实现这样的Equals方法。
public override bool Equals(BaseStaff staff) {
this.anInt == staff.anInt &&
this.aBool == staff.aBool;
}
在AllTheStaff中你可以像这样覆盖这个方法
public override bool Equals(BaseStaff staff) {
bool baseEquals = base.Equals(staff);
bool basicStaffEquals = this.BasicStaff.Equals(staff);
return baseEquals || basicStaffEquals;
}
这只是核心理念,也许我不太了解你真正希望实现的目标,但希望它可以帮助你:)
答案 2 :(得分:0)
测试解决方案
public static bool AllPublicPropertiesEqual<T>(T AObj, T BObj, params string[] ignore) where T : class
{
if (AObj != null && BObj != null)
{
Type type = typeof(T);
List<string> ignoreList = new List<string>(ignore);
foreach (PropertyInfo pInfo in type.GetCType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (!ignoreList.Contains(pInfo.Name))
{
if (pInfo.PropertyType.IsArray)
{
object aElementValues = (type.GetProperty(pInfo.Name).GetValue(AObj, null));
object bElementValues = (type.GetProperty(pInfo.Name).GetValue(BObj, null));
if (aElementValues != null && bElementValues != null)
{
List<object> AListValues = new List<object>();
List<object> BListValues = new List<object>();
foreach (var v in (IEnumerable)aElementValues)
AListValues.Add(v);
foreach (var v in (IEnumerable)bElementValues)
BListValues.Add(v);
if (AListValues.Count == BListValues.Count)
{
object[] aArray = AListValues.ToArray();
object[] bArray = BListValues.ToArray();
for (int i = 0; i < aArray.Length; i++)
{
if (!AllPublicPropertiesEqual(aArray[i], bArray[i]))
return false;
}
}
else
return false;
}
else if ((aElementValues == null) != (bElementValues == null))
return false;
}
else if (!pInfo.PropertyType.IsValueType && !pInfo.PropertyType.IsPrimitive && !pInfo.PropertyType.IsEnum && pInfo.PropertyType != typeof(string))
//else if (Convert.GetTypeCode(pInfo.PropertyType) == TypeCode.Object)
{
object AObjectValue = type.GetProperty(pInfo.Name).GetValue(AObj, null);
object BObjectValue = type.GetProperty(pInfo.Name).GetValue(BObj, null);
if (!AllPublicPropertiesEqual(BObjectValue, AObjectValue))
return false;
}
else
{
object aValue = type.GetProperty(pInfo.Name).GetValue(AObj, null);
object bValue = type.GetProperty(pInfo.Name).GetValue(BObj, null);
if (aValue != bValue && (aValue == null || !aValue.Equals(bValue)))
return false;
}
}
}
return true;
}
return AObj == BObj;
}
}