Search code examples
c#inheritancereflectionrecursionpropertyinfo

How can I recursively search properties in C# only if those properties inherit from some base class?


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?


Solution

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