Сравните два сложных объекта в c# - PullRequest
0 голосов
/ 15 апреля 2020

Я пытаюсь сравнить два объекта и хочу определить разницу в объектах.

Это прекрасно работает, если я не использую List. Но когда я использую List, хотя List в обоих объектах равны, это говорит о том, что оно не равно и go, чтобы проверить List разницу. Поскольку на данный момент у меня нет условия для сравнения списков, оно дает сбой и выдает мне это исключение System.Reflection.TargetParameterCountException: 'Parameter count mismatch.'

Я получил помощь от одного из сообщений stackoverflow из здесь . Вот мой код, который я написал до сих пор.

public class Program
{
    public static void Main()
    {
        Employee emp1 = OldEmployee();

        Employee emp2 = NewEmployee();

        var list = GetDifferingProperties(emp1, emp2);

        foreach (var s in list)
            Console.WriteLine(s);
    }

    public static IList<string> GetDifferingProperties(object source, object target)
    {
        var sourceType = source.GetType();
        var sourceProperties = sourceType.GetProperties();
        var targetType = target.GetType();
        var targetProperties = targetType.GetProperties();

        var result = new List<string>();

        foreach (var property in
            (from s in sourceProperties
             from t in targetProperties
             where s.Name == t.Name &&
             s.PropertyType == t.PropertyType &&
             !Equals(s.GetValue(source, null), t.GetValue(target, null))
             select new { Source = s, Target = t }))
        {
            // it's up to you to decide how primitive is primitive enough
            if (IsPrimitive(property.Source.PropertyType))
            {
                result.Add(property.Source.Name);
            }
            else
            {
                foreach (var subProperty in GetDifferingProperties(
                    property.Source.GetValue(source, null),
                    property.Target.GetValue(target, null)))
                {
                    result.Add(property.Source.Name);
                }
            }
        }

        return result;
    }

    private static bool IsPrimitive(Type type)
    {
        return type == typeof(string)
            || type == typeof(int) || type == typeof(int?)
            || type == typeof(double) || type == typeof(double?)
            || type == typeof(bool) || type == typeof(bool?)
            || type == typeof(Guid) || type == typeof(Guid?)
            || type == typeof(DateTime) || type == typeof(DateTime?);
    }

    public static string GetPropertyDisplayName(PropertyInfo pi)
    {
        var dp = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault();
        return dp != null ? dp.DisplayName : pi.Name;
    }

    private static Employee NewEmployee()
    {
        var contactDetail = new ContactDetails();
        contactDetail.ContactNumber = "123456789";

        var employeeAddress = new Address();
        employeeAddress.AddressLine1 = "Microsoft Corporation";
        employeeAddress.AddressLine2 = "One Microsoft Way";
        employeeAddress.City = "Redmond";
        employeeAddress.State = "WA";
        employeeAddress.Zip = "98052-6399";
        employeeAddress.ContactDetails = new List<ContactDetails>() { contactDetail };

        var employee = new Employee();
        employee.FirstName = "Bill";
        employee.LastName = "Gates";
        employee.MiddleName = "Middle Name";
        employee.IsActive = true;
        employee.JoinDate = new DateTime(2015, 10, 15);
        employee.ReleaseDate = new DateTime(2015, 10, 15);
        employee.EmployeeAddress = employeeAddress;
        return employee;
    }

    private static Employee OldEmployee()
    {
        var contactDetail = new ContactDetails();
        contactDetail.ContactNumber = "123456789";

        var employeeAddress = new Address();
        employeeAddress.AddressLine1 = "Microsoft Corporation";
        employeeAddress.AddressLine2 = "One Microsoft Way";
        employeeAddress.City = "Redmond";
        employeeAddress.State = "WA";
        employeeAddress.Zip = "98052-6399";
        employeeAddress.ContactDetails = new List<ContactDetails>() { contactDetail };

        var employee = new Employee();
        employee.FirstName = "Bill";
        employee.LastName = "Gates";
        employee.MiddleName = "Middle Name";
        employee.IsActive = true;
        employee.JoinDate = new DateTime(2015, 10, 15);
        employee.ReleaseDate = new DateTime(2015, 10, 15);
        employee.EmployeeAddress = employeeAddress;
        return employee;
    }
}

public class ContactDetails
{
    public string ContactNumber { get; set; }
}

public class Address
{
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
    public bool IsActive { get; set; }
    public List<ContactDetails> ContactDetails { get; set; }
}

public class Employee
{
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public bool IsActive { get; set; }
    public DateTime JoinDate { get; set; }
    public DateTime? ReleaseDate { get; set; }
    public Address EmployeeAddress { get; set; }
}

Если я закомментирую строку employeeAddress.ContactDetails = new List<ContactDetails>() { contactDetail }; от oldEmployee и newEmployee, она будет работать нормально, и если есть какая-либо разница в EmployeeAddress, она ее идентифицирует, и если нет никакой разницы, это не так. Но если я раскомментирую эту строку employeeAddress.ContactDetails = new List<ContactDetails>() { contactDetail };, она извлекает EmployeeAddress, поскольку у нее есть различие, хотя это не так. Кто-нибудь может подсказать, что мне не хватает, я потратил много времени на выявление проблемы.

Моя цель - создать список свойств, которые имеют значение в объекте Employee, например

  1. Если FirstName в Employee имеет разницу result список должен содержать только FirstName
  2. Если FirstName в Employee и AddressLine1 в EmployeeAddress имеет разницу result список должен содержать (FirstName, EmployeeAddress)
  3. Аналогично, если FirstName в Employee и ContactNumber в ContactDetails, то есть список в адресе, имеет разницу result список должен содержать (FirstName, EmployeeAddress), в этом случае список результатов по-прежнему содержит EmployeeAddress, потому что ContactNumber находится в EmployeeAddress, который находится в Employee, поэтому наш основной фокус - получить родительские свойства, которые имеют различие между исходным и целевым объектами.

Точка 1 и Точка 2 работают, как ожидалось. Если я закомментирую employeeAddress.ContactDetails = new List<ContactDetails>() { contactDetail };, потому что это вызывает исключение, а также сопровождается изменением, хотя оно не имеет никаких изменений в источнике и цели.

Любая помощь будет высоко оценена, или вы можете предложить мне какую-то другую способ реализации тоже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...