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

时间:2015-12-08 05:00:34

标签: 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; }
    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)
    {
    }

5 个答案:

答案 0 :(得分:2)

如果您正在寻找非常简单的东西,请使用反射。但如果您需要某些高级功能,请使用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);

答案 1 :(得分:1)

反思怎么样:

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

答案 2 :(得分:1)

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

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

那么代码是什么?

  1. 您可以将“属性”数组传递给方法IsAddressModified。比较时将排除这些属性。
  2. 从表达式I中提取MemberExpression以获取每个属性的名称。
  3. 我遍历Address类型的所有属性,并检查它是否是要排除的属性。
  4. 最后但并非最不重要的是,我比较了属性值。
  5. 为什么这么“复杂”?

    使用此解决方案,您可以根据需要将尽可能多的属性传递给函数。在编译期间,您完全是类型安全的。

    在Main中你可以看到我如何调用这个函数。即使AddressID a1a2的{​​{1}}不同,该函数也会返回false,因为您排除了AddressID

    可以找到完整的可编辑示例here

答案 3 :(得分:0)

蛮力?

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
}

答案 4 :(得分:0)

Compare NET Objects拥有您所需的一切!

按表达式忽略

const path = require('path');
const CompressionPlugin = require('compression-webpack-plugin');


module.exports = {
    mode: "development",
    entry: './src/index.js',
    devtool: 'inline-source-map',   // for development build only
    devServer: {
        contentBase: './dist',
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'main.js',                        // for development build only
        // filename: '[name].[contenthash].js',     // for production build only
    },
    plugins: [
        new CompressionPlugin({
            filename: "[path].gz[query]",
            algorithm: "gzip",
            test: /\.(js|css|html|svg)$/
        })
    ],
    module: {
        rules: [
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            },
            { 
                test: /\.(png|woff|woff2|eot|ttf|svg)$/, 
                loader: 'url-loader?limit=100000' 
            },
            {
                test: /\.s[ac]ss$/i,
                use: [
                  'style-loader',   // Creates `style` nodes from JS strings
                  'css-loader',     // Translates CSS into CommonJS
                  'sass-loader',    // Compiles Sass to CSS
                ],
            },
        ]
    }
};

忽略ClassName.MemberName

CompareLogic compare = new CompareLogic();
compare.Config.IgnoreProperty<Person>(x => x.Name);

忽略所有具有名称的成员

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