【问题标题】:Iterating over class properties using LINQ使用 LINQ 迭代类属性
【发布时间】:2012-06-14 12:37:43
【问题描述】:

有一个 ParsedTemplate 类,它有 300 多个属性(类型为 Details 和 BlockDetails)。 parsedTemplate 对象将被一个函数填充。填充此对象后,我需要一个 LINQ(或其他方式)来查找 IsExist=falsePriority="high" 处是否有任何属性,如“body”或“img”。

public class Details
{
    public bool IsExist { get; set; }
    public string Priority { get; set; }
}

public class BlockDetails : Details
{
    public string Block { get; set; }
}

public class ParsedTemplate
{
    public BlockDetails body { get; set; }
    public BlockDetails a { get; set; }
    public Details img { get; set; }
    ...
}

【问题讨论】:

  • 使用反射很容易做到这一点,但我看不出 LINQ 会有什么用处。为什么每个人都试图用 LINQ 解决所有问题?
  • @cadrell0 因为人们倾向于认为 LINQ 是灵丹妙药
  • @cadrell0 和所有那些激光东西的奇怪语法都必须是 LINQ
  • 300 属性听起来是个坏主意。当然,某种形式的集合/层次结构/字典会更好地代表它(因为您似乎正在解析 HTML)。
  • @Ghooti 希望人们只为你编写代码可能不是最好的选择。

标签: c# .net linq linq-to-objects


【解决方案1】:

您将需要编写自己的方法来让这道菜变得可口。幸运的是,它不需要很长时间。比如:

static IEnumerable<Details> GetDetails(ParsedTemplate parsedTemplate)
{
    return from p in typeof(ParsedTemplate).GetProperties()
           where typeof(Details).IsAssignableFrom(p.PropertyType)
           select (Details)p.GetValue(parsedTemplate, null);
}

然后,如果您想检查 ParsedTemplate 对象上是否“存在”任何属性,例如,您可以使用 LINQ:

var existingDetails = from d in GetDetails(parsedTemplate)
                      where d.IsExist
                      select d;

【讨论】:

    【解决方案2】:

    如果你真的想在这样做的时候使用 linq,你可以尝试类似的方法:

    bool isMatching = (from prop in typeof(ParsedTemplate).GetProperties()
                       where typeof(Details).IsAssignableFrom(prop.PropertyType)
                       let val = (Details)prop.GetValue(parsedTemplate, null) 
                       where val != null && !val.IsExist && val.Priority == "high"
                       select val).Any();
    

    在我的机器上工作。

    或者在扩展方法语法中:

    isMatching = typeof(ParsedTemplate).GetProperties()
                     .Where(prop => typeof(Details).IsAssignableFrom(prop.PropertyType))
                     .Select(prop => (Details)prop.GetValue(parsedTemplate, null))
                     .Where(val => val != null && !val.IsExist && val.Priority == "high")
                     .Any();
    

    【讨论】:

      【解决方案3】:

      使用 c# 反射。例如:

      ParsedTemplate obj;
      PropertyInfo pi = obj.GetType().GetProperty("img");
      Details value = (Details)(pi.GetValue(obj, null));
      if(value.IsExist)
      {
         //Do something
      }
      

      我还没有编译,但我认为它可以工作。

      【讨论】:

        【解决方案4】:
                ParsedTemplate tpl = null;
                // tpl initialization
                typeof(ParsedTemplate).GetProperties()
                    .Where(p => new [] { "name", "img" }.Contains(p.Name))
                    .Where(p => 
                        {
                            Details d = (Details)p.GetValue(tpl, null) as Details;
                            return d != null && !d.IsExist && d.Priority == "high"
                        });
        

        【讨论】:

        • 虽然这与 Dan Tao 的答案相同,但它不像他的那样可重复使用(对于它试图解决的问题来说基本上太复杂了如果您需要对任何变化重复此操作)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-19
        • 2017-03-30
        • 1970-01-01
        • 1970-01-01
        • 2016-06-30
        • 2016-06-18
        • 1970-01-01
        相关资源
        最近更新 更多