web-dev-qa-db-ja.com

c#2つのオブジェクトを比較して、値が異なるプロパティを探します

(同じタイプの)2つのオブジェクトを受け取り、異なる値を持つプロパティのリストを返すジェネリックメソッドを作成する必要があります。私の要件は少し異なるので、これは重複しているとは思いません。

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);

コードは要件を説明しています:

public List<string> GetChangedProperties(object A, object B)
{
    List<string> changedProperties = new List<string>();
   //Compare for changed values in properties 
   if(A.Age != B.Age)
   {
       //changedProperties.Add("Age");
   } 
   //Compare other properties
   ..
   ..
   return changedProperties;
}

次のことを検討する必要があります。

  1. 汎用 同じクラスの)任意のタイプのオブジェクトを比較できる必要があります
  2. パフォーマンス
  3. シンプル

箱から出してすぐに利用できるライブラリはありますか?

---(AutoMapper を使用してこれを達成できますか?

6
Rahul

私は少し改善しました クリシュナの答え

public List<string> GetChangedProperties<T>(object A, object B)
{
    if (A != null && B != null)
    {
        var type = typeof(T);
        var allProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        var allSimpleProperties = allProperties.Where(pi => pi.PropertyType.IsSimpleType());
        var unequalProperties =
               from pi in allSimpleProperties
               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();
    }
    else
    {
        throw new ArgumentNullException("You need to provide 2 non-null objects");
    }
}

それは私のために働いていなかったので。これは機能し、それを機能させるために必要な他の唯一のことは、IsSimpleType()-ここから適応した拡張メソッドです この回答 ここ(拡張メソッドに変換しただけです)。

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));
}
6
robkrueger

これを試して。すべてのクラスに対して汎用である必要があります。

 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
Krishna
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;
        }
    }
}
1
Marco Salerno