C# 获取具有相同属性的两个对象之间的差异

C# 获取具有相同属性的两个对象之间的差异,c#,reflection,C#,Reflection,我正在尝试使用EmployeeHistory模型(对象2)获取对员工模型(对象1)所做更改的列表。基本上,只有一个员工记录,但有多个员工历史记录。每次对员工进行更改时,都会将一条新记录添加到EmployeeHistory表中,该表包含更改前员工的数据。我想要一种方法来比较每个EmployeeHistory记录,并返回报告所做更改的字符串列表。因此,为了得到变更列表,我想遍历EmployeeHistory记录列表,并将每个EmployeeHistory记录与以前的EmployeeHistory记录

我正在尝试使用EmployeeHistory模型(对象2)获取对员工模型(对象1)所做更改的列表。基本上,只有一个员工记录,但有多个员工历史记录。每次对员工进行更改时,都会将一条新记录添加到EmployeeHistory表中,该表包含更改前员工的数据。我想要一种方法来比较每个EmployeeHistory记录,并返回报告所做更改的字符串列表。因此,为了得到变更列表,我想遍历EmployeeHistory记录列表,并将每个EmployeeHistory记录与以前的EmployeeHistory记录进行比较。最后一个EmployeeHistory记录需要与属性非常相似的当前雇员(对象1)记录进行比较。有没有什么方法可以做到这一点,而不需要大量的IF语句来比较每个记录上的两个属性

这正是我想要的:

 public List<string> GetEmployeeMasterHistory(Models.EmployeeMaster employee,IEnumerable<EmployeeMasterHistory> employeeHistoryCollection)
 {
       foreach (var historyRecord in employeeHistoryCollection)
       {
          //Compare historyRecord to EmployeeCollection[historyRecord.Index() - 1]
       }
       return null;
 }
公共列表GetEmployeeMasterHistory(Models.EmployeeMaster employee,IEnumerable EmployeeHistory集合)
{
foreach(employeeHistoryCollection中的var historyRecord)
{
//将historyRecord与EmployeeCollection进行比较[historyRecord.Index()-1]
}
返回null;
}
我已经有了一个方法,可以对每个属性进行所有检查,但是将来会添加更多的属性,我已经厌倦了添加新的IF语句,而且它似乎不是很有效

以下是EmployeeMasterHistory记录的外观:

 public partial class EmployeeMasterHistory
    {
        public Nullable<int> EmployeeNumber { get; set; }
        public Nullable<int> CompanyNumber { get; set; }
        public string UserName { get; set; }
        public string Initials { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string FullName { get; set; }
        public Nullable<bool> StatusFlag { get; set; }
        public Nullable<System.DateTime> StartDate { get; set; }
        public Nullable<System.DateTime> TerminationDate { get; set; }
        public string Branch { get; set; }
        public Nullable<int> DepartmentNumber { get; set; }
        public string Supervisor { get; set; }
        public Nullable<int> Shift { get; set; }
        public Nullable<int> UnionNo { get; set; }
        public string G2ID { get; set; }
        public Nullable<bool> EnterTimeFl { get; set; }
        public string Phone { get; set; }
        public string Extension { get; set; }
        public string CellPhone { get; set; }
        public string Email { get; set; }
        public Nullable<int> PrimaryJobRole { get; set; }
        public Nullable<int> JobLevel { get; set; }
        public Nullable<int> JobGroup { get; set; }
        public string JobTitle { get; set; }
        public string EmployeeType { get; set; }
        public string PayType { get; set; }
        public Nullable<decimal> Rate { get; set; }
        public Nullable<System.DateTime> LastReviewDate { get; set; }
        public Nullable<System.DateTime> NextReviewDate { get; set; }
        public Nullable<System.DateTime> LastPayChangeDate { get; set; }
        public string EmergencyContact { get; set; }
        public string EmergencyContactRelationship { get; set; }
        public string EmergencyContactPhone { get; set; }
        public Nullable<bool> CPComputer { get; set; }
        public Nullable<bool> CPPhone { get; set; }
        public Nullable<bool> CPCreditCard { get; set; }
        public Nullable<bool> CPGasCard { get; set; }
        public Nullable<bool> CPKeys { get; set; }
        public Nullable<bool> CPSecurityCard { get; set; }
        public Nullable<bool> CPVehicle { get; set; }
        public Nullable<bool> CPTools { get; set; }
        public Nullable<bool> CPUniform { get; set; }
        public string ModBy { get; set; }
        public Nullable<System.DateTime> ModDate { get; set; }
        public int ID { get; set; }
        public string SalesRep { get; set; }
        public string MiddleName { get; set; }
        public Nullable<int> ManagerEmpNo { get; set; }
        public Nullable<bool> TempFl { get; set; }
        public Nullable<bool> PEWFl { get; set; }
        public Nullable<bool> PGTFl { get; set; }
        public Nullable<bool> PMPFl { get; set; }
        public Nullable<bool> PPGEFl { get; set; }
        public Nullable<bool> PPGFl { get; set; }
        public Nullable<bool> PRCFl { get; set; }
        public Nullable<bool> PTCFl { get; set; }
        public Nullable<bool> PPFl { get; set; }
        public Nullable<bool> SWPFl { get; set; }
        public Nullable<int> PrimaryDivision { get; set; }
        public string TechGroupID { get; set; }
        public string TechLevelID { get; set; }
        public Nullable<bool> TechATD { get; set; }
        public Nullable<int> ReviewPeriod { get; set; }
        public Nullable<bool> CorpFl { get; set; }
    }
公共部分类EmployeeMasterHistory
{
公共可为空的EmployeeNumber{get;set;}
公共可空公司编号{get;set;}
公共字符串用户名{get;set;}
公共字符串首字母{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串全名{get;set;}
公共可空状态标志{get;set;}
公共可为空的起始日期{get;set;}
公共可为空的终止日期{get;set;}
公共字符串分支{get;set;}
公共可为空的部门编号{get;set;}
公共字符串管理器{get;set;}
公共可空移位{get;set;}
公共可为空的UnionNo{get;set;}
公共字符串G2ID{get;set;}
公共可为空的EnterTimeFl{get;set;}
公用字符串电话{get;set;}
公共字符串扩展名{get;set;}
公共字符串{get;set;}
公共字符串电子邮件{get;set;}
公共可为空的PrimaryJobRole{get;set;}
公共可为空的作业级别{get;set;}
可为空的公共作业组{get;set;}
公共字符串JobTitle{get;set;}
公共字符串EmployeeType{get;set;}
公共字符串PayType{get;set;}
公共可空速率{get;set;}
公共可为空的LastReviewDate{get;set;}
公共可为空的NextReviewDate{get;set;}
公共可为空的LastPayChangeDate{get;set;}
公共字符串紧急联系人{get;set;}
公共字符串EmergencyContactRelationship{get;set;}
公共字符串EmergencyContactPhone{get;set;}
公共可为空的CPComputer{get;set;}
公共可空CPPhone{get;set;}
公共可为空的CPCredit卡{get;set;}
公共可为空的CPGasCard{get;set;}
公共可为空的CPKeys{get;set;}
公共可为空的CPSecurityCard{get;set;}
公共可为空的CPVehicle{get;set;}
公共可为空的CPTools{get;set;}
公共可空CPUniform{get;set;}
公共字符串ModBy{get;set;}
公共可为空的ModDate{get;set;}
公共int ID{get;set;}
公共字符串SalesRep{get;set;}
公共字符串MiddleName{get;set;}
公共可为空的ManagerEmpNo{get;set;}
公共可为空的TempFl{get;set;}
公共可为空的PEWFl{get;set;}
公共可空PGTFl{get;set;}
公共可空PMPFl{get;set;}
公共可空PPGEFl{get;set;}
公共可空PPGFl{get;set;}
公共可为空的PRCFl{get;set;}
公共可空PTCFl{get;set;}
公共可空PPFl{get;set;}
公共可空SWPFl{get;set;}
公共可空主除法{get;set;}
公共字符串TechGroupID{get;set;}
公共字符串TechLevelID{get;set;}
公共可为空的TechATD{get;set;}
公共可空的ReviewPeriod{get;set;}
公共可空CorpFl{get;set;}
}

提前谢谢你

下面是一个使用反射的非常简单的方法:

        var oOldRecord = new EmployeeMasterHistory();
        oOldRecord.EmployeeNumber = 1;
        var oNewRecord = new EmployeeMasterHistory();
        oNewRecord.EmployeeNumber = 2;
        oNewRecord.CompanyNumber = 3;

        var oType = oOldRecord.GetType();

        foreach (var oProperty in oType.GetProperties())
        {
            var oOldValue = oProperty.GetValue(oOldRecord, null);
            var oNewValue = oProperty.GetValue(oNewRecord, null);
            // this will handle the scenario where either value is null
            if (!object.Equals(oOldValue, oNewValue))
            {
                // Handle the display values when the underlying value is null
                var sOldValue = oOldValue == null ? "null" : oOldValue.ToString();
                var sNewValue = oNewValue == null ? "null" : oNewValue.ToString();

                System.Diagnostics.Debug.WriteLine("Property " + oProperty.Name + " was: " + sOldValue + "; is: " + sNewValue);
            }
        }
此示例的输出为:

Property EmployeeNumber was: 1; is: 2
Property CompanyNumber was: null; is: 3

这可能需要清理,但应该让您开始走正确的道路。

另一个答案是一个良好的开端。但我继续写了这个更加充实的例子,所以我想我也可以把它贴出来。这个函数处理空值,并提供一种从比较中选择退出属性的方法。它仍然是基本的,但应该会让您更进一步,假设前面提到的库不是您想要使用的

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

namespace TestCompareProperties
{
    class Program
    {
        class IgnorePropertyCompareAttribute : Attribute { }

        class A
        {
            public int Property1 { get; private set; }
            public string Property2 { get; private set; }
            [IgnorePropertyCompare]
            public bool Property3 { get; private set; }

            public A(int property1, string property2, bool property3)
            {
                Property1 = property1;
                Property2 = property2;
                Property3 = property3;
            }
        }

        class PropertyCompareResult
        {
            public string Name { get; private set; }
            public object OldValue { get; private set; }
            public object NewValue { get; private set; }

            public PropertyCompareResult(string name, object oldValue, object newValue)
            {
                Name = name;
                OldValue = oldValue;
                NewValue = newValue;
            }
        }

        private static List<PropertyCompareResult> Compare<T>(T oldObject, T newObject)
        {
            PropertyInfo[] properties = typeof(T).GetProperties();
            List<PropertyCompareResult> result = new List<PropertyCompareResult>();

            foreach (PropertyInfo pi in properties)
            {
                if (pi.CustomAttributes.Any(ca => ca.AttributeType == typeof(IgnorePropertyCompareAttribute)))
                {
                    continue;
                }

                object oldValue = pi.GetValue(oldObject), newValue = pi.GetValue(newObject);

                if (!object.Equals(oldValue, newValue))
                {
                    result.Add(new PropertyCompareResult(pi.Name, oldValue, newValue));
                }
            }

            return result;
        }

        static void Main(string[] args)
        {
            A[] rga = { new A(1, "1", false), new A(2, "1", true), new A(2, null, false) };

            for (int i = 0; i < rga.Length - 1; i++)
            {
                Console.WriteLine("Comparing {0} and {1}:", i, i + 1);
                foreach (PropertyCompareResult resultItem in Compare(rga[i], rga[i+1]))
                {
                    Console.WriteLine("  Property name: {0} -- old: {1}, new: {2}",
                        resultItem.Name, resultItem.OldValue ?? "<null>", resultItem.NewValue ?? "<null>");
                }
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
命名空间TestCompareProperties
{
班级计划
{
类IgnorePropertyCompareAttribute:属性{}
甲级
{
公共int属性1{get;私有集;}
公共字符串属性2{get;private set;}
[IgnorePropertyCompare]
公共布尔属性3{get;private set;}
公共A(int属性1、字符串属性2、布尔属性3)
{
Property1=Property1;
Property2=属性