使用Linq定位嵌套属性

本文关键字:属性 嵌套 定位 Linq 使用 | 更新日期: 2023-09-27 18:06:16

我有一个如下所示的对象模型。

public class Class1
{
    public Class2 @Class2;
}
public class Class2
{
    public Class3 @Class3;
    public Class4 @Class4;
}
public class Class3
{
    public Class5 @Class5;
}
public class Class4
{
    public Class5 @Class5;
}
public class Class5
{
    public Class6 @Class6;
}
public class Class6
{
}

谁能推荐一种方法来迭代层次结构,直到我可以得到Class5的实例,这是Class4的属性?在VS2012上使用。net 4.5, c# .

使用Linq定位嵌套属性

假设"入口点"位于层次结构的"顶部"(例如Class1Class2),我可以想到一些与建议的访问者模式类似的扩展方法。

public static class FieldAndTypeExtensions {
    public static IEnumerable<FieldInfo> walk(this Type t) {
        foreach (FieldInfo f in t.GetFields()) {
            foreach (FieldInfo nextField in f.walk()) {
                yield return nextField;
            }
        }
    }
    public static IEnumerable<FieldInfo> walk(this FieldInfo f) {
        yield return f;
        FieldInfo[] fieldInfos = f.FieldType.GetFields();
        foreach (FieldInfo nextField in fieldInfos) {
            foreach (FieldInfo anotherNext in nextField.walk()) {
                yield return anotherNext;
            }
        }
    }
}

可能的用法是:

Type t = typeof(Class1);
var allFieldsFound = from field
                     in t.walk()
                     where field.FieldType == typeof(Class5)
                     select field;
var firstFound = allFieldsFound.FirstOrDefault();                        

firstFoundallFieldsFound中的条目都是FieldInfo类型的,因此您可以通过其DeclaringType属性获得声明(封闭)类。

也许这不是最优雅的解决方案,但可能是一个基本的想法。

这样做的典型方法是使用Visitor模式。在你的例子中,你的Visit方法将使用反射来"打开"传入的类型。

这里有一个很好的例子,如何构造一个表达式树访问器,它做的事情与您想要的类似(层次结构爬行)。