两种型号之间的差异

时间:2018-10-23 10:46:14

标签: c#

是否可以比较两个模型并仅显示差异,例如已更新,添加或删除的内容?

例如,在以下模型中,我创建了多个Sample模型:

var grocers1 = new List<Grocer>();

var grocer1 = new Grocer
{
    Id = 1,
    Expenditure = 500,
    Name = "Bob"
};

grocers1.Add(grocer1);

var grocers2 = new List<Grocer>();

var grocer2 = new Grocer
{
    Id = 1,
    Expenditure = 300,
    Name = "Bob"
};

grocers2.Add(grocer2);

var fruits = new List<Fruit>();

var fruit1 = new Fruit();

fruits.Add(fruit1);

var orders1 = new List<Order>();

var order1 = new Order
{
    Id = 1,
    SampleId = 1,
    Fruits = fruits
};

var order2 = new Order
{
    Id = 1,
    SampleId = 1,
    Fruits = fruits
};

orders1.Add(order1);
orders1.Add(order2);

var orders2 = new List<Models.Documents.Order> {order1};

var sample = new Sample
{
    Id = 1,
    Date = Convert.ToDateTime("2018-10-23"),
    Grocers = grocers1,
    Orders = orders1
};

var changedSample = new Sample
{
    Id = 1,
    Date = Convert.ToDateTime("2018-10-22"),
    Grocers = grocers2,
    Orders = orders1
};

var otherChangedSample = new Sample
{
    Id = 1,
    Date = Convert.ToDateTime("2018-10-23"),
    Grocers = grocers1,
    Orders = orders2
};

因此,如果我将samplechangedSample进行比较,它应该仅显示日期已从2018-10-23更改为2018-10-22,并且支出已从500更改为300。 / p>

然后,如果我将sampleotherChangedSample进行比较,则应该表明order2已被删除。

最后,如果我将otherChangedSamplesample进行比较,则表明已经添加了2号订单。

我已经用AutoMapper测试过,这对于比较相同的基本模型(不包括列表)非常有用,它很好地突出了更改。

然后我尝试了Compare-Net-Objects,这很好,这一次确实考虑了列表并突出显示了更改,但前提是列表数量保持不变。它将识别列表计数的更改,但不会告诉您已删除的值或已添加的值。

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

您也可以使用反射和扩展方法:

var sample = new Sample
{
    Id = 1,
    Date = Convert.ToDateTime("2018-10-23"),
    Grocers = grocers1,
    Orders = orders1
};

var otherChangedSample = new Sample
{
    Id = 1,
    Date = Convert.ToDateTime("2018-10-23"),
    Grocers = grocers1,
    Orders = orders2
};

class Variance
{
    public string Prop { get; set; }
    public object valA { get; set; }
    public object valB { get; set; }
}
List<Variance> rt = sample.DetailedCompare(otherChangedSample);

using System.Collections.Generic;
using System.Reflection;

static class extentions
{
    public static List<Variance> DetailedCompare<T>(this T val1, T val2)
    {
        List<Variance> variances = new List<Variance>();
        FieldInfo[] fi = val1.GetType().GetFields();
        foreach (FieldInfo f in fi)
        {
            Variance v = new Variance();
            v.Prop = f.Name;
            v.valA = f.GetValue(val1);
            v.valB = f.GetValue(val2);
            if (!v.valA.Equals(v.valB))
                variances.Add(v);

        }
        return variances;
    } 
}

答案 1 :(得分:0)

您是否自己编写了模型类代码?如果不是这样,则必须处理反射(速度可能很慢,并且必须进行很多编程才能覆盖所有数据类型),或者要处理序列化(序列化为字符串并进行字符串比较)。

如果您可以扩展您的类,那么我将为每个单独的类添加一个方法:

internal void TrackChange(T other, List<Change> changes)

您的课程Sampe中的此方法如下:

void TrackChange(Sample other, List<Change> changes)
{
    if (this.Id != other.Id) changes.add(new Change(...));
    if (this.Date != other.Date) changes.add(new Change(...));
    if (this.Grocers.count != other.Grocers.count) changes.add(new Change(...)); // number of items has changed
    for (int i = 0; i < math.min(this.grocers.count, other.grocers.count); i++)
        this.grocers[i].TrackChange(other.grocers[i], changes);
    ....
}

Grocer类具有其自己的TrackChange方法。等等。

这是一些编码,但是效率最高,您可以自己处理所有情况。例如,如果您不介意列表中的杂货店顺序,则可以迭代此列表中的所有杂货店,并尝试在其他列表中找到对应的杂货店(例如,按ID),然后致电TrackChange。