Question

I'm trying to loop through a class and it's child classes to get the values passed with it.

Here's my class:

public class MainClass
{
    bool IncludeAdvanced { get; set; }

    public ChildClass1 ChildClass1 { get; set; }
    public ChildClass2 ChildClass2 { get; set; }
}

Here's my code so far

GetProperties<MainClass>();

private void GetProperties<T>()
{
    Type classType = typeof(T);
    foreach (PropertyInfo property in classType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
    {
        WriteToLog(property.Name + ": " + property.PropertyType + ": " + property.MemberType);
        GetProperties<property>();
    }
}

Two questions:

  1. What do I pass to GetProperties, to pass the child class, for it to then loop through it's properties if it's a class?
  2. How do I get the value from the property item if it isn't a class?

Hopefully this all makes sense. If not, don't hesitate to ask and I'll try and clarify.

Thanks

Was it helpful?

Solution 2

Chris already answered the first part of your question, so I won't repeat that. For the second part, as soon as you have an instance of MainClass, you can just use the (aptly named) PropertyInfo.GetValue method:

object value = property.GetValue(myInstance, null);

(If you use .NET 4.5, you can omit the second (null) parameter. Earlier versions require it, though.)

In the end, your code could look like this (I shamelessly copied and extended Chris' version) (untested):

private void GetProperties<T>(T instance)
{
    GetProperties(typeof(T), instance);
}

private void GetProperties(Type classType, object instance)
{
    foreach (PropertyInfo property in classType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
    {
        WriteToLog(property.Name + ": " + property.PropertyType + ": " + property.MemberType);

        object value = property.GetValue(instance, null);
        if (value != null) {
            WriteToLog(value.ToString());
            GetProperties(property.PropertyType, value);
        }
    }
}

Note that this code will fail if any of your objects use indexed properties (C# indexers or properties with parameters in VB). In that case, GetValue would need to be provided with the appropriate index or parameter.

OTHER TIPS

You can easily rewrite it to be recursive without generics:

private void GetProperties<T>()
{
    GetProperties(typeof(T));
}

private void GetProperties(Type classType)
{
    foreach (PropertyInfo property in classType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
    {
        WriteToLog(property.Name + ": " + property.PropertyType + ": " + property.MemberType);
        GetProperties(property.PropertyType);
    }
}

Not sure on your second question "how do I get the value from the property item if it isn't a class" (I'll edit/update when we figure that out)

Regarding your second question, if you want to get the value from the property item, you must provide the object of the Type. Heinzi has explained how to get the value by the property. I provide a shell version without generics.

 private static void ResolveTypeAndValue(object obj)
    {
        var type = obj.GetType();
        foreach (var p in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
        {
            if (p.PropertyType.IsClass && p.PropertyType != typeof(string))
            {
                var currentObj = p.GetValue(obj);
                ResolveTypeAndValue(currentObj);
            }
            else
                Console.WriteLine("The value of {0} property is {1}", p.Name, p.GetValue(obj));
        }
    }
public IEnumerable<PropertyInfo> GetProperties(Type type)
    {
        //Just to avoid the string
        if (type == typeof(String)) return new PropertyInfo[] { };
        var properties = type.GetProperties().ToList();
        foreach (var p in properties.ToList())
        {
            if (p.PropertyType.IsClass)
                properties.AddRange(GetProperties(p.PropertyType));
            else if (p.PropertyType.IsGenericType)
            {
                foreach (var g in p.PropertyType.GetGenericArguments())
                {
                    if (g.IsClass)
                        properties.AddRange(GetProperties(g));
                }
            }
        }
        return properties;

    }

Try this which iterates over properties only if it is class

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top