区分具有相同属性的两个对象

时间:2014-10-17 19:26:54

标签: c# reflection

我正在尝试使用EmployeeHistory模型(对象2)获取对Employee模型(对象1)所做更改的列表。基本上,只有一个员工记录,但有几个EmployeeHistory记录。每次在Employee上更改某些内容时,都会在EmployeeHistory表中添加一条新记录,该表包含更改之前Employee的数据。我想要一种比较每个EmployeeHistory记录的方法,并返回一个报告所做更改的字符串列表。因此,为了获取更改列表,我想迭代EmployeeHistory记录列表,并将每个EmployeeHistory Record与之前的EmployeeHistory记录进行比较。并且最后一个EmployeeHistory记录需要与当前的Employee(对象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;
 }

我已经有一个方法可以对每个属性进行所有检查,但是将来会添加更多属性,我厌倦了必须添加新的IF语句,它似乎不太高效。

以下是EmployeeMasterHistory Record的内容:

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

提前谢谢!

2 个答案:

答案 0 :(得分:23)

这是一种使用反射的非常简单的方法:

        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

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

答案 1 :(得分:16)

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

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