仅当这些属性继承自某个基类时,如何才能在 C# 中递归搜索这些属性?

发布于 2024-12-26 00:58:01 字数 1027 浏览 1 评论 0原文

仅当属性的类型继承自某个基类时,如何递归获取对象的所有属性?

这是我的尝试:

static IEnumerable<PropertyInfo> FindProperties(object objectTree, Type targetType)
{
    if (objectTree.GetType().IsAssignableFrom(targetType))
    {
        var properties = objectTree.GetType().GetProperties();
        foreach (var property in properties)
        {
            yield return property;
        }

        foreach (var property in FindProperties(properties, targetType))
        {
            yield return property;
        }
    }
}

所以我可以调用,

var allPropertiesOfPageTypes = FindProperties(someClass, typeof(Page));

但是,返回的属性数量始终为零。我做错了什么?

编辑:

我不确定这是否重要,但子类是通用类:

public abstract class MasterPage<T> : BasePage<T> where T : MasterPage<T>

继承:

public abstract class BasePage<T> : Page where T : BasePage<T>

从 Master/BasePage 继承的东西似乎为 IsAssignableFrom 返回 false?

How can I recursively get all the properties of an object only if the type of the property inherits from some base class?

This was my attempt:

static IEnumerable<PropertyInfo> FindProperties(object objectTree, Type targetType)
{
    if (objectTree.GetType().IsAssignableFrom(targetType))
    {
        var properties = objectTree.GetType().GetProperties();
        foreach (var property in properties)
        {
            yield return property;
        }

        foreach (var property in FindProperties(properties, targetType))
        {
            yield return property;
        }
    }
}

So I could call,

var allPropertiesOfPageTypes = FindProperties(someClass, typeof(Page));

However, the number of properties returned is always zero. What am I doing wrong?

Edit:

I'm not sure if this matters but the subclasses are generic classes:

public abstract class MasterPage<T> : BasePage<T> where T : MasterPage<T>

That inherits:

public abstract class BasePage<T> : Page where T : BasePage<T>

Things that inherit from Master/BasePage seem to be returning false for IsAssignableFrom?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

任性一次 2025-01-02 00:58:01

仅当您具有正确的类型并且需要实例而不是属性本身时才需要递归:

static IEnumerable<PropertyInfo> FindProperties(object objectTree, Type targetType)
{
    if (targetType.IsAssignableFrom(objectTree.GetType()))
    {
        var properties = objectTree.GetType().GetProperties();
        foreach (var property in properties)
        {
            yield return property;

            if (targetType.IsAssignableFrom(property.PropertyType))
            {
                object instance = property.GetValue(objectTree, null);
                foreach (var subproperty in FindProperties(instance, targetType))
                {
                    yield return subproperty;
                }
            }
        }
    }
}

You need to only recurse when you have the right type, and you need an instance, not the property itself:

static IEnumerable<PropertyInfo> FindProperties(object objectTree, Type targetType)
{
    if (targetType.IsAssignableFrom(objectTree.GetType()))
    {
        var properties = objectTree.GetType().GetProperties();
        foreach (var property in properties)
        {
            yield return property;

            if (targetType.IsAssignableFrom(property.PropertyType))
            {
                object instance = property.GetValue(objectTree, null);
                foreach (var subproperty in FindProperties(instance, targetType))
                {
                    yield return subproperty;
                }
            }
        }
    }
}
丘比特射中我 2025-01-02 00:58:01

为了验证一个对象是否继承自另一个类,您必须执行与您正在执行的操作相反的操作:

 if (targetType.IsAssignableFrom(objectTree.GetType()))

这与以下方式类似:

Parent o = new Derived();

In order to verify if an object inherits from another class you have to do the opposite of what you are doing:

 if (targetType.IsAssignableFrom(objectTree.GetType()))

this works in a similar way to:

Parent o = new Derived();
眼泪都笑了 2025-01-02 00:58:01

也许这可以工作?

public static LinkedPageElement<TElement> GetLinkedElement<TPage, TElement>(Page page, bool verbose = true) where TElement : class
{
    var propInfos = page.GetType().GetProperties();

    // First try to find the property in the current page type
    foreach (var propInfo in propInfos)
    {
        var attributes = propInfo.GetCustomAttributes(typeof(LinkedPageAttribute), true);
        if (attributes.Length == 0) continue;

        var linkedPageAttribute = (from a in attributes where a.GetType() == typeof(LinkedPageAttribute) select a).FirstOrDefault();
        if (linkedPageAttribute == null || !(linkedPageAttribute is LinkedPageAttribute)) continue;

        if ((linkedPageAttribute as LinkedPageAttribute).PageType == typeof(TPage))
        {
            return new LinkedPageElement<TElement>
            {
                Element = propInfo.GetValue(page, null) as TElement,
                AutoClick = (linkedPageAttribute as LinkedPageAttribute).AutoClick
            };
        }
    }

    // Then try to find it in a property
    var containedInProperty = propInfos.Where(x => x.PropertyType.IsSubclassOf(typeof(Page)))
        .Select(x => GetLinkedElement<TPage, TElement>((Page)x.GetValue(page, null), false))
        .FirstOrDefault(x => x != null);

    if (containedInProperty != null) return containedInProperty;

    // you are trying to navigate to a page which cannot be reached from the current page, check to see you have a link with LinkedPage attribute
    if (verbose)
        throw new ArgumentException("You don't have a link to this page {0} from this page {1}".FormatWith(typeof(TPage), page.GetType()));

    return null;
}

Maybe this could work?

public static LinkedPageElement<TElement> GetLinkedElement<TPage, TElement>(Page page, bool verbose = true) where TElement : class
{
    var propInfos = page.GetType().GetProperties();

    // First try to find the property in the current page type
    foreach (var propInfo in propInfos)
    {
        var attributes = propInfo.GetCustomAttributes(typeof(LinkedPageAttribute), true);
        if (attributes.Length == 0) continue;

        var linkedPageAttribute = (from a in attributes where a.GetType() == typeof(LinkedPageAttribute) select a).FirstOrDefault();
        if (linkedPageAttribute == null || !(linkedPageAttribute is LinkedPageAttribute)) continue;

        if ((linkedPageAttribute as LinkedPageAttribute).PageType == typeof(TPage))
        {
            return new LinkedPageElement<TElement>
            {
                Element = propInfo.GetValue(page, null) as TElement,
                AutoClick = (linkedPageAttribute as LinkedPageAttribute).AutoClick
            };
        }
    }

    // Then try to find it in a property
    var containedInProperty = propInfos.Where(x => x.PropertyType.IsSubclassOf(typeof(Page)))
        .Select(x => GetLinkedElement<TPage, TElement>((Page)x.GetValue(page, null), false))
        .FirstOrDefault(x => x != null);

    if (containedInProperty != null) return containedInProperty;

    // you are trying to navigate to a page which cannot be reached from the current page, check to see you have a link with LinkedPage attribute
    if (verbose)
        throw new ArgumentException("You don't have a link to this page {0} from this page {1}".FormatWith(typeof(TPage), page.GetType()));

    return null;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文