比较2个对象并检索具有不同值的字段列表

给定一个具有35个字段的类和2个具有一定数量的不同字段值的对象。 是否有一种聪明的方法来获取列表以及对象如下所示的字段名称?

例如

obj1.Name = "aaa"; obj1.LastName = "bbb"; obj1.Address = "xcs"; obj2.Name = "aaa"; obj2.LastName = "ccc"; obj2.Address = "jk"; 

目的:

 list<String> containing 2 Strings LastName and Address 

我认为reflection是要走的路,但是35场,恐怕太重了。 还有其他想法,比如linq?

好; 这比我通常会花费更多的努力,但这可能是一个有用的实用方法。 它动态创建IL(缓存)来完成工作,处理值类型vs ref类型对象,内置IL等式,等式运算符( == )和EqualityComparer用于其余的:

 using System.Collections.Generic; using System.Reflection; using System.Reflection.Emit; namespace ConsoleApplication2 { using System; class Program { static void Main() { WriteDeltas(new Foo {X = 123, Y = DateTime.Today, Z = null}, new Foo {X = 124, Y = DateTime.Today, Z = null}); WriteDeltas(new Foo { X = 123, Y = DateTime.Today, Z = null }, new Foo { X = 123, Y = DateTime.Now, Z = new Dummy()}); WriteDeltas(new Bar { X = 123, Y = DateTime.Today, Z = null }, new Bar { X = 124, Y = DateTime.Today, Z = null }); WriteDeltas(new Bar { X = 123, Y = DateTime.Today, Z = null }, new Bar { X = 123, Y = DateTime.Now, Z = new Dummy() }); } static void WriteDeltas(T x, T y) { Console.WriteLine("----"); foreach(string delta in PropertyComparer.GetDeltas(x,y)) { Console.WriteLine(delta); } } } class Dummy {} class Foo { public int X { get; set; } public DateTime Y { get; set; } public Dummy Z { get; set; } } struct Bar { public int X { get; set; } public DateTime Y { get; set; } public Dummy Z { get; set; } } public static class PropertyComparer { private static readonly Func> getDeltas; static PropertyComparer() { var dyn = new DynamicMethod(":getDeltas", typeof (List), new[] {typeof (T), typeof (T)},typeof(T)); var il = dyn.GetILGenerator(); il.Emit(OpCodes.Newobj, typeof (List).GetConstructor(Type.EmptyTypes)); bool isValueType = typeof (T).IsValueType; OpCode callType = isValueType ? OpCodes.Call : OpCodes.Callvirt; var add = typeof(List).GetMethod("Add"); foreach (var prop in typeof(T).GetProperties()) { if (!prop.CanRead) continue; Label next = il.DefineLabel(); switch (Type.GetTypeCode(prop.PropertyType)) { case TypeCode.Boolean: case TypeCode.Byte: case TypeCode.Char: case TypeCode.Double: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.SByte: case TypeCode.Single: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: if(isValueType) {il.Emit(OpCodes.Ldarga_S, (byte)0);} else {il.Emit(OpCodes.Ldarg_0);} il.EmitCall(callType, prop.GetGetMethod(), null); if (isValueType) { il.Emit(OpCodes.Ldarga_S, (byte)1); } else { il.Emit(OpCodes.Ldarg_1); } il.EmitCall(callType, prop.GetGetMethod(), null); il.Emit(OpCodes.Ceq); break; default: var pp = new Type[] {prop.PropertyType, prop.PropertyType}; var eq = prop.PropertyType.GetMethod("op_Equality", BindingFlags.Public | BindingFlags.Static, null, pp, null); if (eq != null) { if (isValueType) { il.Emit(OpCodes.Ldarga_S, (byte)0); } else { il.Emit(OpCodes.Ldarg_0); } il.EmitCall(callType, prop.GetGetMethod(), null); if (isValueType) { il.Emit(OpCodes.Ldarga_S, (byte)1); } else { il.Emit(OpCodes.Ldarg_1); } il.EmitCall(callType, prop.GetGetMethod(), null); il.EmitCall(OpCodes.Call, eq, null); } else { il.EmitCall(OpCodes.Call, typeof(EqualityComparer<>).MakeGenericType(prop.PropertyType).GetProperty("Default").GetGetMethod(), null); if (isValueType) { il.Emit(OpCodes.Ldarga_S, (byte)0); } else { il.Emit(OpCodes.Ldarg_0); } il.EmitCall(callType, prop.GetGetMethod(), null); if (isValueType) { il.Emit(OpCodes.Ldarga_S, (byte)1); } else { il.Emit(OpCodes.Ldarg_1); } il.EmitCall(callType, prop.GetGetMethod(), null); il.EmitCall(OpCodes.Callvirt, typeof(EqualityComparer<>).MakeGenericType(prop.PropertyType).GetMethod("Equals", pp), null); } break; } il.Emit(OpCodes.Brtrue_S, next); // equal il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldstr, prop.Name); il.EmitCall(OpCodes.Callvirt, add, null); il.MarkLabel(next); } il.Emit(OpCodes.Ret); getDeltas = (Func>)dyn.CreateDelegate(typeof (Func>)); } public static List GetDeltas(T x, T y) { return getDeltas(x, y); } } } 

反思是采用这种方式的方式,我不认为35个字段是个问题。

(在完全迷惑自己后,我回过头来以为我理解这个问题并且反思对此很好)。