我有几个复杂的对象,我想比较属性。以下代码做得很好,直到你到达集合。我想以集合的每个成员递归调用该函数。有人可以看看并帮我确定集合中的对象类型,以便我可以再次调用HasPropertyChanged吗?
这个伪代码显示了我的意图
if (p.GetType() == typeof(System.Collections.Generic.List<>))
{
foreach (var blah in //the list)
{
HasPropertyChanged<//TheType>(Type obj1, Type obj2, null);
}
}
此外,这部分代码让我感到困惑。如果我不调用tostring方法,我会得到一些时髦的结果,比如id 63633不等于63633
object val1 = Original.GetType().GetProperty(p.Name).GetValue(Original, null);
object val2 = Modified.GetType().GetProperty(p.Name).GetValue(Modified, null);
if (!IgnoreProperties.Contains(p.Name) &&
val1 != null && val2 != null &&
val1.ToString() != val2.ToString())
{
return true;
}
这是完整的。
private bool HasPropertyChanged<T>(T Original, T Modified, string[] IgnoreProperties)
{
if (Original == null || Modified == null)
return false;
if (IgnoreProperties == null)
IgnoreProperties = new string[] { };
IEnumerable<PropertyInfo> properties = typeof(T).GetProperties();
foreach (var p in properties)
{
if (p.GetType() == typeof(System.Collections.Generic.List<>))
{
foreach (var blah in //the list)
{
HasPropertyChanged<//TheType>(Type obj1, Type obj2, null);
}
}
object val1 = Original.GetType().GetProperty(p.Name).GetValue(Original, null);
object val2 = Modified.GetType().GetProperty(p.Name).GetValue(Modified, null);
if (!IgnoreProperties.Contains(p.Name) &&
val1 != null && val2 != null &&
val1.ToString() != val2.ToString())
{
return true;
}
}
return false;
}
答案 0 :(得分:1)
由于您在运行时处理类型,因此您应该使用函数的非泛型版本,该版本采用Type
参数:
private bool HasPropertyChanged<T>(T Original, T Modified, string[] IgnoreProperties)
{
return HasPropertyChanged(typeof(T), Original, Modified, IgnoreProperties);
}
private bool HasPropertyChanged(Type T, object Original, object Modified, string[] IgnoreProperties)
{
// ...
}
使用它,您可以调用列表元素的方法:
if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.List<>))
{
object val1 = p.GetValue(Original, null);
object val2 = p.GetValue(Modified, null);
// First check count...
PropertyInfo countProperty = p.PropertyType.GetProperty("Count");
int count1 = countProperty.GetValue(val1, null);
int count2 = countProperty.GetValue(val2, null);
if (count1 != count2) return true;
// Now iterate:
var enumerator1 = (val1 as System.Collections.IEnumerable).GetEnumerator();
var enumerator2 = (val2 as System.Collections.IEnumerable).GetEnumerator();
while (enumerator1.MoveNext())
{
enumerator2.MoveNext();
// check for null, skipping here...
object elem1 = enumerator1.Current;
object elem2 = enumerator2.Current;
if (HasPropertyChanged(elem1.GetType(), elem1, elem2, IgnoreProperties)) return true;
}
}
// ...
答案 1 :(得分:1)
首先,您需要注意使用==而不是Equals()。您将所有属性值提取为对象;
object val1 = Original.GetType().GetProperty(p.Name).GetValue(Original, null);
object val2 = Modified.GetType().GetProperty(p.Name).GetValue(Modified, null);
然后使用相等运算符来比较它们。对于引用类型,此运算符仅在它们是同一实例时才返回true,在这种情况下,它们永远不会 - 因为val1和val2是2个不同的对象。您可以删除.ToString()调用并替换为;
if (val1.Equals(val2) { ... }
对于您正在尝试做的事情,这是一种更正确的方法(我假设)。
现在收集问题 - 为什么不试试;
if (p is IEnumerable)
{
foreach (object o in p)
{
if (!o.HasPropertyChanged(...))
return false;
}
}
我认为你不需要用泛型来实现它。我能看到的泛型类型的唯一目的是确保传入的类型是相同的。所以,只需删除它,将T更改为'Type'或'object',并对函数的第一行中的类型进行比较;
if (Original.GetType() != Modified.GetType())
return false;