我正在尝试比较C#中的两个复杂对象,并生成一个包含两者之间差异的字典。
如果我有这样的课程:
public class Product
{
public int Id {get; set;}
public bool IsWhatever {get; set;}
public string Something {get; set;}
public int SomeOtherId {get; set;}
}
一个例子,因此:
var p = new Product
{
Id = 1,
IsWhatever = false,
Something = "Pony",
SomeOtherId = 5
};
和另一个:
var newP = new Product
{
Id = 1,
IsWhatever = true
};
为了得到这些之间的差异,我正在做包括这个的东西:
var oldProps = p.GetType().GetProperties();
var newProps = newP.GetType().GetProperties();
// snip
foreach(var newInfo in newProps)
{
var oldVal = oldInfo.GetValue(oldVersion, null);
var newVal = newInfo.GetValue(newVersion,null);
}
// snip - some ifs & thens & other stuff
这就是感兴趣的这条线
var newVal = newInfo.GetValue(newVersion,null);
使用上面的示例对象,此行将为SomeOtherId
提供默认值0(bools& DateTimes& whathaveyou的相同故事)。
我正在寻找的方法是让newProps
仅包含对象中明确指定的属性,因此在上面的示例中,Id
和IsWhatever
。我玩过BindingFlags
无济于事。
这可能吗?是否有更清洁/更好的方法来做到这一点,或者有一个工具来帮助我省去麻烦?
感谢。
答案 0 :(得分:2)
如果您明确设置了某个属性,则没有标记。您可以做的是将属性声明为可空类型,并将值与null进行比较。
答案 1 :(得分:1)
如果我理解正确的话,这就是微软对xml包装类所做的,使用xsd实用程序生成,对于每个属性XIsSpecified
,你有一个X
或类似的东西。
所以这也是你可以做的 - 而不是public int ID{get;set;}
,添加一个私有成员_id
,或者你选择调用它的任何东西,以及一个布尔属性IDSpecified
每当调用Id
的setter时都设置为true
答案 2 :(得分:0)
我最终修复了这个问题而没有使用反射(或者至少没有以这种方式使用它)。
或多或少,这样:
public class Comparable
{
private IDictionary<string, object> _cache;
public Comparable()
{
_cache = new Dictionary<string, object>();
}
public IDictionary<string, object> Cache { get { return _cache; } }
protected void Add(string name, object val)
{
_cache.Add(name, val);
}
}
产品实施到此:
public class Product : Comparable
{
private int _id;
private bool _isWhatever;
private string _something;
private int _someOtherId;
public int Id {get { return _id; } set{ _id = value; Add("Id", value); } }
public bool IsWhatever { get { return _isWhatever; } set{ _isWhatever = value; Add("IsWhatever ", value); } }
public string Something {get { return _something; } set{ _something = value; Add("Something ", value); } }
public int SomeOtherId {get { return _someOtherId; } set{ _someOtherId = value; Add("SomeOtherId", value); } }
}
然后比较非常简单
var dic = new Dictionary<string, object>();
foreach(var obj in version1.Cache)
{
foreach(var newObj in version2.Cache)
{
//snip -- do stuff to check equality
dic.Add(....);
}
}
模型不会非常脏,而且效果很好。