Я пытаюсь сравнить два объекта и хочу определить разницу в объектах.
Это прекрасно работает, если я не использую 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, например
- Если
FirstName
в Employee
имеет разницу result
список должен содержать только FirstName - Если
FirstName
в Employee
и AddressLine1
в EmployeeAddress
имеет разницу result
список должен содержать (FirstName, EmployeeAddress) - Аналогично, если
FirstName
в Employee
и ContactNumber
в ContactDetails
, то есть список в адресе, имеет разницу result
список должен содержать (FirstName, EmployeeAddress), в этом случае список результатов по-прежнему содержит EmployeeAddress
, потому что ContactNumber
находится в EmployeeAddress, который находится в Employee, поэтому наш основной фокус - получить родительские свойства, которые имеют различие между исходным и целевым объектами.
Точка 1 и Точка 2 работают, как ожидалось. Если я закомментирую employeeAddress.ContactDetails = new List<ContactDetails>() { contactDetail };
, потому что это вызывает исключение, а также сопровождается изменением, хотя оно не имеет никаких изменений в источнике и цели.
Любая помощь будет высоко оценена, или вы можете предложить мне какую-то другую способ реализации тоже.