【问题标题】:Lambda for finding differences in properties with reflection not returning correctly in C#用于查找属性差异的 Lambda 在 C# 中没有正确返回反射
【发布时间】:2014-08-26 16:28:03
【问题描述】:

我正在尝试根据其他一些帖子解决问题。我正在查看列表中具有相同属性的多个对象,并且我需要验证它们在每个对象中都是相同的值。如果不是,我需要标记对象具有冲突的属性值。我正在尝试并且可以工作的代码如下,但始终返回 true 以将属性添加到列表中,即使列表项中的值都相同。

public List<string> JobHasConflictingTaxForms(Job job, List<string> propertiesToCheck)
{
    var conflictingPropertiesList = new List<string>();

    foreach(string prop in propertiesToCheck)
    {
         if (!job.TaxForms.TrueForAll(t => t.ARecord.GetType().GetProperty(prop)
                          .GetValue(t.ARecord, null) ==
                           job.TaxForms[0].ARecord.GetType().GetProperty(prop)
                          .GetValue(job.TaxForms[0].ARecord, null)))
         {
             conflictingPropertiesList.Add(prop);
         }
    }

    return conflictingPropertiesList;
}

每个税表都有一个名为“ARecord”的属性对象。这些是我需要验证的属性对于每个税表来说是普遍相同的,如果不是,那么我需要标记一个存在差异。我错过了什么,或者这个 lambda 语句做错了什么?即使我具有所有相同的值,或者具有相同值的三种形式,而一种具有不同属性的形式,它也会返回相同的结果。它总是返回 true。

附:我也尝试过使用 Any(i => logic != other item)。但并没有按照我的预期工作。

TaxForm 类

 public class TaxForm 
{
    #region Properties

    public string TaxFormType
    {
        get;
        set;
    }

    public string FileName
    {
        get;
        set;
    }

    public string FileFullName
    {
        get;
        set;
    }

    public bool ShouldProcess
    {
        get;
        set;
    }

    public bool Corrected
    {
        get;
        set;
    }

    public TRecord TRecord
    {
        get;
        set;
    }

    public ARecord ARecord
    {
        get;
        set;
    }

    public BRecord BRecord
    {
        get;
        set;
    }

    public List<string> BRecords
    {
        get;
        set;
    }

    public bool HasConflictingrecords
    {
        get;
        set;
    }

    public bool HasDataConflict
    {
        get;
        set;
    }

    #endregion

}

现在是 ARecord 类

public class ARecord
{
    #region Properties
    /// <summary>
    /// Found at POS(12) for 8
    /// </summary>
    public string PayerTIN
    {
        get;
        set;
    }

    /// <summary>
    /// Found at POS(38) for 39.
    /// </summary>
    public string PayerName
    {
        get;
        set;
    }

    /// <summary>
    /// Found at POS(134) for 39.
    /// </summary>
    public string PayerAddress
    {
        get;
        set;
    }

    /// <summary>
    /// found at POS(255) for 14.
    /// </summary>
    public string PayerPhone
    {
        get;
        set;
    }

    /// <summary>
    /// Found at POS(2) for 3.
    /// </summary>
    public string PayerYear
    {
        get;
        set;
    }

    #endregion


}

【问题讨论】:

  • 房产类型有哪些?它们本身是不是一个集合?
  • 没有。唯一的集合是 TaxForms。然后是一个对象属性ARecord。然后其上的常规属性都是字符串类型。所以 ARecord 不是一个集合,也没有任何集合。我可以发布两个类的快速示例。
  • 我希望它被清楚地解释并在代码中显示我想要在这里完成的内容。如果不是,我可以给出更多解释。希望使用反射方法以更少的代码来处理这个问题。
  • 如果所有属性都是字符串,请尝试使用静态 string.Equals 方法而不是 == 运算符。在这种情况下,== 运算符可能正在执行引用比较而不是值比较。不是说它是,而是用其他方法试试看它是否有所作为。在查找PropertyInfo.GetValue 方法时,它返回一个Object。对象的 == 运算符进行引用比较。您需要转换为 string 并进行字符串相等比较。
  • @Casey 我建议你在网上搜索一个图书馆来做你想做的事。您为实现此方法而选择的路线非常缓慢。互联网上应该有很多例子展示了如何通过使用在运行时编译的缓存Func&lt;T, T, bool&gt; 来做同样的事情,它的性能要高得多。您可以选择使用纯 IL 或表达式树来编写它。

标签: c# .net reflection lambda


【解决方案1】:

PropertyInfo.GetValue 方法将其引用的属性值返回为类型Object。执行的 == 运算符是 Object 类的运算符,而不是 String 的运算符。

要执行正确的比较方法,您需要将调用 PropertyInfo.GetValue 的返回值转换为 string,然后使用 == 运算符或调用静态 string.Equals 方法。

【讨论】:

    【解决方案2】:

    @Tony 的建议,它们是通过对象实例进行比较的,而不是实际的字符串值。以下代码纠正了问题,并给了我正确的结果。

    foreach(string prop in propertiesToCheck)
            {
                 if(!job.TaxForms.TrueForAll(t => t.ARecord.GetType().GetProperty(prop).GetValue(t.ARecord, null).ToString().Equals(job.TaxForms[0].ARecord.GetType().GetProperty(prop).GetValue(job.TaxForms[0].ARecord, null).ToString())))
                 {
                     conflictingPropertiesList.Add(prop);
                 }
            }
    

    所以这样应该更好?

    【讨论】:

    • 只要有 null 值,此代码就会中断。
    • 没错。我确实检查了空条目,并且不要将属性保留为空。您不能只使用 Convert.ToString(null as object) 来获取返回的 "" 值来处理它吗?以防有人想知道并想要使用类似的东西。
    • 您应该只使用string.Equals 来比较字符串。清晰、直接、有效。
    猜你喜欢
    • 1970-01-01
    • 2015-12-23
    • 2021-06-25
    • 1970-01-01
    • 2018-10-21
    • 2010-10-22
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多