C# 如何比较两个对象-排除比较中的特定属性

C# 如何比较两个对象-排除比较中的特定属性,c#,.net,C#,.net,我有一个例子,我想比较c#中的两个对象。我还可以选择在比较时排除特定属性。有谁能提出更好的方法吗。类将如下所示 public class Address { public string AddressID { get; set; } public int AddressStagingID { get; set; } public string Address1 { get; set; } public string Address2 { get; set; }

我有一个例子,我想比较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)
    {
    }
蛮力

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
}
蛮力

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
}
反思如何:

  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;    
            }
        }
反思如何:

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

我尝试使用表达式树开发一个不同的解决方案,在我看来,它更灵活

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;
  }
}
公共类测试
{
公共静态void Main()
{
地址a1=新地址();
a1.AddressID=“100”;
地址a2=新地址();
a2.AddressID=“200”;
Console.WriteLine(isAddressResmodified(a1,a2,a=>a.AddressID));
}

public static bool IsAddressModified(地址a1、地址a2、参数表达式我尝试使用表达式树开发一个不同的解决方案,在我看来,它更灵活

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;
  }
}
公共类测试
{
公共静态void Main()
{
地址a1=新地址();
a1.AddressID=“100”;
地址a2=新地址();
a2.AddressID=“200”;
Console.WriteLine(isAddressResmodified(a1,a2,a=>a.AddressID));
}

public static bool IsAddressModified(地址a1、地址a2、参数表达式如果您正在寻找非常简单的东西,请使用反射。但是如果您需要高级的东西,请使用。这是。此库还可以提供有关更改的详细报告。这意味着您可以使用它进行日志记录等

这是来自该站点的示例代码

//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);

如果您正在寻找非常简单的东西,请使用反射。但是如果您需要高级的东西,请使用。这是。此库还可以提供有关更改的详细报告。这意味着您可以将其用于日志记录等

这是来自该站点的示例代码

//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);
有你需要的一切

以表达方式忽略

忽略具有名称的所有成员

用通配符忽略

使用属性忽略

仅将属性与属性进行比较

有你需要的一切

以表达方式忽略

忽略具有名称的所有成员

用通配符忽略

使用属性忽略

仅将属性与属性进行比较


当你说两个对象时,你是指两个类型为
Address
的实例吗?@Kosala W..Yes.question updated当你说两个对象时,你是指两个类型为
Address
的实例吗?@Kosala W..Yes.question updated回答得很好。
公共静态bool是否可以进行地址修改(地址a1,地址a2,参数表达式[]props)
进行重构,使其成为
T
的通用对象,如
修改了公共静态bool(T a1、T a2、参数表达式[]props)
?这行得通吗?当然,只需将我与正在运行的示例的链接进行更改即可。注意:上面的示例仅部分通用,使用System。对象不是类型安全的…此处更新的示例:非常好的答案。
公共静态bool是否可以进行地址修改(地址a1、地址a2、参数表达式[]props)
进行重构,使其对
T
通用,如
公共静态bool已修改(T a1,T a2,params Expression[]props)
?这样行吗?当然,只需将我与运行示例的链接进行更改即可。注意:上面的示例仅部分通用,使用System。对象不是类型安全的…更新示例如下:
[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));