c#比较具有不同值的属性的两个对象

时间:2017-03-15 12:24:48

标签: c# object compare comparison automapper

我需要创建一个泛型方法,它将获取两个对象(相同类型),并返回具有不同值的属性列表。 由于我的要求有点不同,我不认为这是重复的。

             left_Handed   right_Handed
  Female          59         4922
  Male            55         4964

代码解释了要求:

public class Person
{
   public string Name {get;set;}
   public string Age {get;set;}
}

Person p1 = new Person{FirstName = "David", Age = 33}
Person p2 = new Person{FirstName = "David", Age = 44}

var changedProperties = GetChangedProperties(p1,p2);

应考虑以下事项:

  1. Generic - 应该能够比较任何类型的对象(具有相同的类)
  2. 性能
  3. 简单
  4. 那里有没有可用的库吗?

    我可以使用AutoMapper实现此目的吗?

4 个答案:

答案 0 :(得分:6)

我在Krishnas answer上做了一点改进:

public static bool IsSimpleType(this Type type)
{
    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
    {
        // nullable type, check if the nested type is simple.
        return type.GetGenericArguments()[0].IsSimpleType();
    }
    return type.IsPrimitive
      || type.IsEnum
      || type.Equals(typeof(string))
      || type.Equals(typeof(decimal));
}

因为它不适合我。这个,并且唯一需要使其工作的是IsSimpleType() - 我在this answer改编的扩展方法(我只将其转换为扩展方法)。

   root
   |-- id: string (nullable = true)
   |-- info: array (nullable = true)
   |    |-- element: struct (containsNull = true)
   |    |    |-- _1: string (nullable = true)
   |    |    |-- _2: long (nullable = false)
   |    |    |-- _3: string (nullable = true)

答案 1 :(得分:2)

试试这个。对于任何一个班级都应该是通用的。

 public List<string> GetChangedProperties(object A, object B)
    {
       if (A!= null && B != null)
        {
            var type = typeof(T);
         var unequalProperties =
                from pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                where pi.GetUnderlyingType().IsSimpleType() && pi.GetIndexParameters().Length == 0
                let AValue = type.GetProperty(pi.Name).GetValue(A, null)
                let BValue = type.GetProperty(pi.Name).GetValue(B, null)
                where AValue != BValue && (AValue == null || !AValue.Equals(BValue))
                select pi.Name;
     return unequalProperties.ToList();
         }
    }

答案 2 :(得分:1)

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

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person("David", 33);
            Person p2 = new Person("David", 44);

            var changedProperties = GetChangedProperties(p1, p2);
        }

        public class Person
        {
            public Person(string name, int age)
            {
                this.name = name;
                this.age = age;
            }

            public int age { get; set; }
            public string name { get; set; }
        }

        public static List<string> GetChangedProperties(Object A, Object B)
        {
            if (A.GetType() != B.GetType())
            {
                throw new System.InvalidOperationException("Objects of different Type");
            }
            List<string> changedProperties = ElaborateChangedProperties(A.GetType().GetProperties(), B.GetType().GetProperties(), A, B);
            return changedProperties;
        }


        public static List<string> ElaborateChangedProperties(PropertyInfo[] pA, PropertyInfo[] pB, Object A, Object B)
        {
            List<string> changedProperties = new List<string>();
            foreach (PropertyInfo info in pA)
            {
                object propValueA = info.GetValue(A, null);
                object propValueB = info.GetValue(B, null);
                if (propValueA != propValueB)
                {
                    changedProperties.Add(info.Name);
                }
            }
            return changedProperties;
        }
    }
}

答案 3 :(得分:-1)

这是我能提出的最简单的解决方案。通用,高效和简单。但是,先决条件是如果任何属性是类对象,则它们必须正确实现等于。

public List<string> GetChangedProperties<T>(T a, T b) where T:class
{   
    if (a != null && b != null)
    {
        if (object.Equals(a, b))
        {
            return new List<string>();
        }
        var allProperties = a.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
        return allProperties.Where(p => !object.Equals( p.GetValue(a),p.GetValue(b))).Select(p => p.Name).ToList();
    }
    else
    {
        var aText = $"{(a == null ? ("\"" + nameof(a) + "\"" + " was null") : "")}";
        var bText = $"{(b == null ? ("\"" + nameof(b) + "\"" + " was null") : "")}";
        var bothNull = !string.IsNullOrEmpty(aText) && !string.IsNullOrEmpty(bText);
        throw new ArgumentNullException(aText + (bothNull ? ", ":"" )+ bText );
    }
}