Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 比较两个对象并检索具有不同值的字段列表_C#_Linq - Fatal编程技术网

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

C# 比较两个对象并检索具有不同值的字段列表,c#,linq,C#,Linq,给定一个包含35个字段和2个具有一定数量不同字段值的对象的类。 有没有一种聪明的方法可以获得一个包含字段名的列表,其中的对象如下所示 e、 g 目标: list<<String>String> containing 2 Strings LastName and Address 包含两个字符串LastName和Address的列表 我认为倒影是一种方式,但对于35个领域,我担心它太重了。 任何其他的想法,比如linq?反射就是解决这个问题的方法,我不认为35个字段是一个

给定一个包含35个字段和2个具有一定数量不同字段值的对象的类。 有没有一种聪明的方法可以获得一个包含字段名的列表,其中的对象如下所示

e、 g

目标:

list<<String>String> containing 2 Strings LastName and Address
包含两个字符串LastName和Address的列表
我认为倒影是一种方式,但对于35个领域,我担心它太重了。
任何其他的想法,比如linq?

反射就是解决这个问题的方法,我不认为35个字段是一个问题

(完全弄糊涂了之后,我想我理解这个问题,反思一下就可以了)。

好;这比我通常要付出的努力多得多,但这可能是一种有用的实用方法。它动态创建IL(缓存)来完成工作,处理值类型与引用类型对象、内置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>(T x, T y)
        {
            Console.WriteLine("----");
            foreach(string delta in PropertyComparer<T>.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<T>
    {
        private static readonly Func<T, T, List<string>> getDeltas;
        static PropertyComparer()
        {
            var dyn = new DynamicMethod(":getDeltas", typeof (List<string>), new[] {typeof (T), typeof (T)},typeof(T));
            var il = dyn.GetILGenerator();
            il.Emit(OpCodes.Newobj, typeof (List<string>).GetConstructor(Type.EmptyTypes));
            bool isValueType = typeof (T).IsValueType;
            OpCode callType = isValueType ? OpCodes.Call : OpCodes.Callvirt;
            var add = typeof(List<string>).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<T, T, List<string>>)dyn.CreateDelegate(typeof (Func<T, T, List<string>>));
        }
        public static List<string> GetDeltas(T x, T y) { return getDeltas(x, y); }

    }
}
使用System.Collections.Generic;
运用系统反思;
使用System.Reflection.Emit;
命名空间控制台应用程序2
{
使用制度;
班级计划
{
静态void Main()
{
WriteDeltas(新的Foo{X=123,Y=DateTime.Today,Z=null},
新Foo{X=124,Y=DateTime.Today,Z=null});
WriteDeltas(新的Foo{X=123,Y=DateTime.Today,Z=null},
新Foo{X=123,Y=DateTime.Now,Z=newdummy()});
WriteDelta(新条{X=123,Y=DateTime.Today,Z=null},
新条{X=124,Y=DateTime.Today,Z=null});
WriteDelta(新条{X=123,Y=DateTime.Today,Z=null},
新条{X=123,Y=DateTime.Now,Z=newdummy()});
}
静态void writedelta(tx,ty)
{
控制台写入线(“---”);
foreach(PropertyComparer.getDelta(x,y)中的字符串增量)
{
控制台写入线(增量);
}
}
}
类虚拟{}
福班
{
公共整数X{get;set;}
公共日期时间Y{get;set;}
公共伪Z{get;set;}
}
结构条
{
公共整数X{get;set;}
公共日期时间Y{get;set;}
公共伪Z{get;set;}
}
公共静态类属性比较程序
{
私有静态只读函数getDelta;
静态属性比较程序()
{
var dyn=newdynamicmethod(“:getDelta”,typeof(List),new[]{typeof(T),typeof(T)},typeof(T));
var il=dyn.GetILGenerator();
Emit(opcode.Newobj,typeof(List).GetConstructor(Type.EmptyTypes));
bool isValueType=typeof(T)。isValueType;
OpCode callType=isValueType?OpCode.Call:OpCode.Callvirt;
var add=typeof(List).GetMethod(“add”);
foreach(typeof(T).GetProperties()中的var prop)
{
如果(!prop.CanRead)继续;
Label next=il.DefineLabel();
开关(Type.GetTypeCode(prop.PropertyType))
{
大小写类型代码。布尔值:
大小写类型代码。字节:
case TypeCode.Char:
案例类型代码。双:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
案例类型代码.SByte:
案例类型代码。单个:
案例类型代码.UInt16:
案例类型代码.UInt32:
案例类型代码.UInt64:
if(isValueType){il.Emit(OpCodes.Ldarga_S,(byte)0);}else{il.Emit(OpCodes.Ldarg_0);}
EmitCall(callType,prop.getMethod(),null);
if(isValueType){il.Emit(opcode.Ldarga_S,(byte)1);}else{il.Emit(opcode.Ldarg_1);}
EmitCall(callType,prop.getMethod(),null);
发射(操作码Ceq);
打破
违约:
var pp=新类型[]{prop.PropertyType,prop.PropertyType};
var eq=prop.PropertyType.GetMethod(“op_Equality”,BindingFlags.Public | BindingFlags.Static,null,pp,null);
如果(等式!=null)
{
if(isValueType){il.Emit(OpCodes.Ldarga_S,(byte)0);}else{il.Emit(OpCodes.Ldarg_0);}
EmitCall(callType,prop.getMethod(),null);
if(isValueType){il.Emit(opcode.Ldarga_S,(byte)1);}else{il.Emit(opcode.Ldarg_1);}
EmitCall(callType,prop.getMethod(),null);
il.EmitCall(操作码.Call,eq,null);
}
其他的
{
EmitCall(OpCodes.Call,typeof(EqualityComparer).MakeGenericType(prop.PropertyType).GetProperty(“默认”).getMethod(),null);
if(isValueType){il.Emit(OpCodes.Ldarga_S,(byte)0);}else{il.Emit(OpCodes.Ldarg_0);}
EmitCall(callType,prop.getMethod(),null);
if(isValueType){il.Emit(opcode.Ldarga_S,(byte)1);}else{il.Emit(opcode.Ldarg_1);}
EmitCall(callType,prop.getMethod(),null);
EmitCall(OpCodes.Callvirt,typeof(EqualityComparer).MakeGenericType(prop.PropertyType).GetMethod(“Equals”,pp),null);
}
打破
}
il.Emit(OpCodes.Brtrue_S,next);//相等
发射(操作码Dup);
il.Emit(opcode.Ldstr,prop.Name);
EmitCall(OpCodes.Callvirt,add,null);
il.MarkLabel(下一页)
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>(T x, T y)
        {
            Console.WriteLine("----");
            foreach(string delta in PropertyComparer<T>.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<T>
    {
        private static readonly Func<T, T, List<string>> getDeltas;
        static PropertyComparer()
        {
            var dyn = new DynamicMethod(":getDeltas", typeof (List<string>), new[] {typeof (T), typeof (T)},typeof(T));
            var il = dyn.GetILGenerator();
            il.Emit(OpCodes.Newobj, typeof (List<string>).GetConstructor(Type.EmptyTypes));
            bool isValueType = typeof (T).IsValueType;
            OpCode callType = isValueType ? OpCodes.Call : OpCodes.Callvirt;
            var add = typeof(List<string>).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<T, T, List<string>>)dyn.CreateDelegate(typeof (Func<T, T, List<string>>));
        }
        public static List<string> GetDeltas(T x, T y) { return getDeltas(x, y); }

    }
}