1

假设以下类:

public class MyEntity
{
    public string FirstName;
    public string LastName;
}

我想比较 的两个实例MyEntity,并创建一个MyEntity仅包含其他两个实例之间值差异的新实例。相等的属性将null在新对象中产生一个值。

例如,我想要以下代码:

MyEntity entity1 = new MyEntity() { FirstName = "Jon", LastName = "Doh" };
MyEntity entity2 = new MyEntity() { FirstName = "Jon", LastName = "The Great" };
MyEntity diffEntity = CreateDiffEntity(entity1, entity2);  // TODO 

产生以下diffEntity值:

{
    FirstName: null,
    LastName: "The Great"
}

我们可以假设所有属性都可以为空。

如果值不匹配,新对象应该包含第二个对象的属性值。

请假设我有许多类型的实体,具有不同的属性定义
所以我需要一个可以用于除 之外的其他类类型的解决方案MyEntity,并且在将新属性添加到类时不需要更改。

最终目标是使客户端移动应用程序能够将仅包含对实体所做更改的 DTO 发送到 ASP.NET MVC WebAPI 服务器应用程序。

如何正确地做到这一点?

4

5 回答 5

4

你可以使用反射来解决这个问题。它的基本要点是:

    public void Compare(object first,object second, object result)
    {
        Type t = first.GetType();
        PropertyInfo[] propertyInfoList =  t.GetProperties();

        foreach (PropertyInfo propertyInfo in propertyInfoList)
        {
            object value1=  propertyInfo.GetValue(first, null);
            object value2 = propertyInfo.GetValue(second, null);

            if (value1 != value2)
            {
                propertyInfo.SetValue(result, value1, null);
            }
            else
            {
               propertyInfo.SetValue(result, null, null);
            }

        }
    }

然后像这样使用它:

MyType result = new MyType();
Compare(object1,object2, result);

它可以用作扩展方法或您的一个实体的成员。

于 2013-08-20T18:23:06.607 回答
2

整个方法存在一个大问题:您不能将任何内容设置为null. 您可能应该只是发送完整的实体,或者,如果您的接口只允许编辑属性的子集,则为每个接口创建一个 DTO,其中仅包含可能发生的更改。


无论如何,只是因为它已经成熟,可以进行一些简单的改进,这是一个基于BrianV 解决方案的通用且稍作修改的解决方案。(使用object.Equals而不是!=允许通过它们的值来比较事物,而不仅仅是它们的身份)

public T Compare<T>(T first, T second) where T : new()
{
    T result = new T();
    Type t = typeof(T);
    PropertyInfo[] propertyInfoList =  t.GetProperties();

    foreach (PropertyInfo propertyInfo in propertyInfoList)
    {
        object value1 = propertyInfo.GetValue(first, null);
        object value2 = propertyInfo.GetValue(second, null);

        if (!object.Equals(value1, value2))
            propertyInfo.SetValue(result, value2, null);
    }

    return result;
}

像这样使用它:

MyEntity entity1 = new MyEntity() { FirstName = "Jon", LastName = "Doh" };
MyEntity entity2 = new MyEntity() { FirstName = "Jon", LastName = "The Great" };
MyEntity diffEntity = Compare(entity1, entity2);
于 2013-08-20T18:33:02.350 回答
1

干得好:

    static public T CreateDiffEntity<T>(T entity1, T entity2) where T : new()
    {
        T result = new T();
        foreach (var property in typeof(T).GetProperties())
        {
            var valuePropertyEntity1 = property.GetValue(entity1);
            var valuePropertyEntity2 = property.GetValue(entity2);
            if (!valuePropertyEntity1.Equals(valuePropertyEntity2))
                property.SetValue(result, valuePropertyEntity2);
            else
                property.SetValue(result, null);
        }
        return result;
    }
于 2013-08-20T18:29:39.480 回答
0

您可以像这样解决您的问题:

public MyEntity CreateDiffEntity(MyEntity entity1, MyEntity entity2) {
    MyEntity diff = new MyEntity();
    diff.FirstName = !entity1.FirstName.equals(entity2.FirstName) ? entity2.FirstName : string.Empty;
    diff.LastName = !entity1.LastName.equals(entity2.LastName) ? entity2.LastName : string.Empty;
    return diff;
}
于 2013-08-20T18:17:38.010 回答
0

你可以在对象初始化器中做到这一点

MyEntity entity1 = new MyEntity() { FirstName = "Jon", LastName = "Doh" };
MyEntity entity2 = new MyEntity() { FirstName = "Jon", LastName = "The Great" };

MyEntity diffEntity = new MyEntity
     {
         FirstName = (entity1.FirstName == entity2.FirstName) ? null : entity2.FirstName,
         LastName = (entity1.LastName == entity2.LastName) ? null : entity2.LastName
     };
于 2013-08-20T18:18:51.350 回答