如何比较两个对象-在比较中排除特定属性
本文关键字:比较 排除 属性 两个 何比较 对象 | 更新日期: 2023-09-27 18:26:00
我有一个案例,我想比较c#中的两个对象。此外,在比较时,我可以选择排除特定的属性。有人能提出更好的方法吗。类将如下所示
public class Address
{
public string AddressID { get; set; }
public int AddressStagingID { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string County { get; set; }
public string Postcode { get; set; }
public string Country { get; set; }
public bool PreferredAddress { get; set; }
public int? DBID { get; set; }
public Enum AddressStatus Status { get; set; }
}
我需要一个类似的功能
private bool IsAddressModified(Address currentAddress,Address existingAddress)
{
}
Compare NET对象拥有您所需要的一切!
按表达式忽略
CompareLogic compare = new CompareLogic();
compare.Config.IgnoreProperty<Person>(x => x.Name);
按ClassName.MemberName忽略
CompareLogic compare = new CompareLogic();
compare.Config.MembersToIgnore.Add("Person.Name");
忽略具有名称的所有成员
CompareLogic compare = new CompareLogic();
compare.Config.MembersToIgnore.Add("UpdateDate");
使用通配符忽略
CompareLogic compare = new CompareLogic();
compare.Config.MembersToIgnore.Add("*Id");
使用属性忽略
[AttributeUsage(AttributeTargets.Property)]
public sealed class CompareIgnoreAttribute : Attribute
{
}
public class Shipment
{
public long IdentCode { get; set; }
public String Customer { get; set; }
[CompareIgnore]
public DateTime InsertDate { get; set; }
}
CompareLogic compare = new CompareLogic();
compare.Config.AttributesToIgnore.Add(typeof(CompareIgnoreAttribute));
仅比较属性和属性
public class Movie
{
[Compare]
public string Name { get; set; }
public decimal PaymentForTomCruise { get; set; }
}
CompareLogic compare = new CompareLogic();
compare.Config.RequiredAttributesToCompare.Add(typeof(CompareAttribute));
我试图使用表达式树开发一个不同的解决方案,在我看来,这是更灵活的
public class Test
{
public static void Main()
{
Address a1 = new Address();
a1.AddressID = "100";
Address a2 = new Address();
a2.AddressID = "200";
Console.WriteLine(IsAddressModified(a1,a2,a=>a.AddressID));
}
public static bool IsAddressModified(Address a1,Address a2,params Expression<Func<Address,Object>>[] props)
{
if(props == null)
return a1.Equals(a2);
foreach(Expression<Func<Address,object>> memberExpression in props)
{
MemberExpression property = memberExpression.Body as MemberExpression;
if(property != null)
{
foreach(PropertyInfo pi in typeof(Address).GetProperties())
{
// exclude all properties we passed in
if(!pi.Name.Equals(property.Member.Name))
{
var valueA1 = pi.GetValue(a1);
var valueA2 = pi.GetValue(a2);
if(valueA1 != null && valueA2 != null)
if(!valueA1.Equals(valueA2))
return true;
}
}
}
}
return false;
}
}
那么代码是什么呢?
- 您可以将一个"属性"数组传递给方法
IsAddressModified
。比较时将排除这些属性 - 从表达式中,我提取一个MemberExpression来获得每个属性的名称
- 我遍历类型
Address
的所有属性,并检查它是否是要排除的一个属性 - 最后但同样重要的是,我比较了属性值
为什么这么"复杂"
使用此解决方案,您可以向函数中传递任意多的属性,并且在编译过程中完全是类型安全的。
在Main中,你可以看到我是如何调用这个函数的。即使由于a1
和a2
的AddressID
不同,函数也会返回false,因为您排除了AddressID
。
完整的可编译示例可以在这里找到
反射如何:
private bool IsAddressModified(Address currentAddress, Address existingAddress)
{
foreach (PropertyInfo pi in currentAddress.GetType().GetProperties())
{
//To exclude properties use condition
if (pi.Name != "City") {
object currentElement = typeof(Address).GetProperty(pi.Name).GetValue(currentAddress,null);
object existingElement = typeof(Address).GetProperty(pi.Name).GetValue(existingAddress,null);
if (!currentElement.Equals(existingElement))
{ return false; }
}
return true;
}
}
如果您正在寻找非常简单的东西,请使用反射。但是,如果您需要高级内容,请使用CompareObjects。这是Nuget。此库还可以提供有关更改的详细报告。这意味着你可以使用它来记录等
这是来自该网站的示例代码。
//This is the comparison class
CompareLogic compareLogic = new CompareLogic();
//Create a couple objects to compare
Person person1 = new Person();
person1.DateCreated = DateTime.Now;
person1.Name = "Greg";
Person person2 = new Person();
person2.Name = "John";
person2.DateCreated = person1.DateCreated;
ComparisonResult result = compareLogic.Compare(person1, person2);
//These will be different, write out the differences
if (!result.AreEqual)
Console.WriteLine(result.DifferencesString);
暴力?
private bool IsAddressModified(Address a, Address b)
{
return a.Address1 != b.Address1 || a.Address2 != b.Address2
|| a.City != b.City || a.PostCode != b.PostCode;
// etc. for all the properties that are considered as modified
}