2

我正在尝试比较 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);

使用上面的示例对象,这一行会给我一个默认值 0 SomeOtherId(对于 bools & DateTimes & whathaveyou 的情况相同)。

我正在寻找的是一种newProps仅包含对象中明确指定的属性的方法,因此在上面的示例中,Id并且IsWhatever. 我玩了BindingFlags几次都没有用。

这可能吗?有没有更清洁/更好的方法,或者有什么工具可以帮我省去麻烦?

谢谢。

4

3 回答 3

2

没有标志可以告诉您是否明确设置了属性。您可以做的是将您的属性声明为可空类型并将值与空值进行比较。

于 2013-03-14T14:59:39.840 回答
1

如果我理解正确,这就是微软使用 xsd 实用程序生成的 xml 包装类所做的事情,其中XIsSpecified​​每个属性都有一个或类似的东西X

所以这也是你可以做的——而不是public int ID{get;set;},添加一个私有成员_id,或者你选择调用它的任何东西,以及一个布尔属性,每当调用 setter时,该属性IDSpecified将设置为 trueId

于 2013-03-14T15:00:20.973 回答
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(....);
    }
}

不会严重弄脏模型,并且效果很好。

于 2013-03-14T20:31:35.040 回答