我正在编写一个 Windows 应用商店应用程序,它从服务器接收一个对象(我创建的自定义类型),让用户编辑该对象,然后将“变更集”提交回服务器。这个变更集只是一个与接收到的对象类型相同的对象,除了用户编辑的字段外,每个字段都设置为空。然后这些字段包含用户的编辑,如下所示:
Original Case: Description: "Cracked exhaust pipe" Status: "Open" Customer: "" Mileage: 10000 Edited Case: Description: "" Status "Open" Customer: "Example inc." Mileage: 10000 Case changeset: Description: "" Status: null Customer: "Example inc." Mileage: null
When the app first downloads the object from the server I make a copy of it for later comparison. The user then makes changes to one of the objects and when the user submits his changes, a changeset of these two objects is calculated with a generic method CalculateChangeSet
. It goes through every property of the two objects and compares them for equality:
public static T CalculateChangeSet<T>(T oldObject, T newObject) where T : new()
{
T changeSet = (T)Activator.CreateInstance(oldObject.GetType());
foreach (PropertyInfo property in oldObject.GetType().GetRuntimeProperties())
{
var oldValue = property.GetValue(oldObject);
var newValue = newObject.GetType().GetRuntimeProperty(property.Name).GetValue(newObject);
if (oldValue != null && newValue != null)
{
if (oldValue is IList)
{
Type listType = oldValue.GetType().GetRuntimeProperty("Item").PropertyType;
IList<listType> oldList = (IList<listType>)oldValue; //Visual studio complains about
IList<listType> newList = (IList<listType>)newValue; //listType not being found
if (!oldList.SequenceEqual(newList))
{
changeSet.GetType().GetRuntimeProperty(property.Name).SetValue(changeSet, newValue, null);
}
}
else
{
if (!oldValue.Equals(newValue))
{
changeSet.GetType().GetRuntimeProperty(property.Name).SetValue(changeSet, CalculateChangeSet(oldValue, newValue));
}
}
}
else
{
changeSet.GetType().GetRuntimeProperty(property.Name).SetValue(changeSet, newValue);
}
}
return changeSet;
}
该方法适用于我遇到的每个属性,但列表除外,因此我创建了 if 子句来处理列表。自 list1.Equals(list2)
不比较列表中的项目,我们需要转换 oldValue
和 newValue
至 List<T>
能够使用 list.SequenceEqual()
.
为什么我会收到一条错误消息 The type or namespace name 'listType' could not be found (are you missing a using directive or an assembly reference?)
当我尝试使用它来创建新列表时?如果有更好的方法来解决这个问题,我愿意接受建议..
最佳答案
试试这个:
IList oldList = (IList)oldValue; //Visual studio complains about
IList newList = (IList)newValue; //listType not being found
if (!NonGenericSequenceEqual(oldList, newList))
{
changeSet.GetType().GetRuntimeProperty(property.Name).SetValue(changeSet, newValue, null);
}
public static bool NonGenericSequenceEqual(IList a, IList b)
{
if (ReferenceEquals(a, b))
{
return true;
}
else if (a == null || b == null)
{
return false;
}
else
{
int count = a.Count;
if (count != b.Count)
{
return false;
}
else
{
for (int i = 0; i < count; i++)
{
if (!Object.Equals(a[i], b[i]))
{
return false;
}
}
return true;
}
}
}
弱代码是'Object.Equals(a[i], b[i])'
通过反射的另一种变体:
if (!(bool)typeof(System.Linq.Enumerable).GetMethod("SequenceEqual").MakeGenericMethod(oldValue.GetType().GetRuntimeProperty("Item").PropertyType).Invoke(null, new object[] { oldObject, newObject }))
{
changeSet.GetType().GetRuntimeProperty(property.Name).SetValue(changeSet, newValue, null);
}
关于c# - 计算对象的变更集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15832079/