使用LINQ迭代类属性

6

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

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

5
使用反射实现这很容易,但我不知道LINQ会有什么用。为什么每个人都试图用LINQ解决所有问题? - cadrell0
2
@cadrell0 因为人们往往认为LINQ是一种万能解决方案。 - sloth
2
@cadrell0和所有那些执行激光操作的奇怪语法一定是LINQ。 - sloth
5
“300个属性”听起来不太合适。使用某种形式的集合/层次结构/字典可能更能代表它(因为您似乎正在解析HTML)。 - iCollect.it Ltd
2
@Ghooti 可能不是最好的想法,希望别人只是为你编写代码。 - Chad Ruppert
显示剩余5条评论
4个回答

7

您需要编写自己的方法来使其更加吸引人。幸运的是,它不需要太长。可以像这样:

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;

3
如果你真的想在这样做的同时使用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();

1
使用C#反射。例如:
ParsedTemplate obj;
PropertyInfo pi = obj.GetType().GetProperty("img");
Details value = (Details)(pi.GetValue(obj, null));
if(value.IsExist)
{
   //Do something
}

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


0
        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"
                });

虽然这个方法和陶丹的答案一样,但它不如他的可重用性强(基本上对于它试图解决的问题来说过于复杂,如果你需要为任何变化重复此操作)。 - iCollect.it Ltd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接