我需要创建一个泛型方法,它将获取两个对象(相同类型),并返回具有不同值的属性列表。 由于我的要求有点不同,我不认为这是重复的。
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);
应考虑以下事项:
那里有没有可用的库吗?
我可以使用AutoMapper实现此目的吗?
答案 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 );
}
}