C# Recursion using reflection on a where type constraint

73 views Asked by At

I'm trying to do recursion through a class but I can't see how I can invoke it with a type constraint.

My problem is mainly I don't know how to invoke the recursion and pass the property type on the Analyze call.

Here's my code:

public class recursor 
{
    public string Analyze<T>() where T : class, new() 
    {
        StringBuilder sb = new StringBuilder();

        T t = new T();

        var propList = t.GetType().GetProperties();

        foreach (var prop in propList)
        {
            System.TypeCode propertyTypeCode = Type.GetTypeCode(prop.PropertyType);

            if (prop.PropertyType.IsClass)
            {
                // THIS IS WHAT I CAN'T FIGURE IT OUT
                // sb.Append(this.Analyze());
            }
            else
            {
                sb.Append("not a class");
            }
        }

        return sb.ToString();
    }
}

public class A {}

public class B {}

public class C {}
  
public class _container 
{
    public A _a;
    public B _b;
    public C _c;
}

public void main() 
{
   var r = new recursor();
   var s = r.Analyze<_container>();
}
2

There are 2 answers

1
Enigmativity On BEST ANSWER

This should help you to move on:

public class recursor
{
public string Analyze<T>() where T : class
{
    StringBuilder sb = new StringBuilder();

    var propList = typeof(T).GetProperties();

    foreach (var prop in propList)
    {
        System.TypeCode propertyTypeCode = Type.GetTypeCode(prop.PropertyType);
        if (prop.PropertyType.IsClass)
        {
            sb.Append(this.GetType().GetMethod("Analyze").MakeGenericMethod(prop.PropertyType).Invoke(this, null).ToString());
            sb.Append(prop.Name);
        }
        else
        {
            sb.Append("not a class");
        }
    }
    return sb.ToString();
}    

public class A { }
public class B { }
public class C { }

public class _container
{
    public A _a { get; set; }
    public B _b { get; set; }
    public C _c { get; set; }
}

That produces _a_b_c for me.

It's recursing and getting a result. You'll need to make sense of it for what you need.


Here's an entirely better version of the method:

public string Analyze2<T>() where T : class
    => this.Analyze2(typeof(T));

public string Analyze2(Type type)
    => String.Concat(
        type
            .GetProperties()
            .Select(p =>
                p.PropertyType.IsClass
                ? this.Analyze2(p.PropertyType)
                : "not a class"));
2
SomeBody On

Your generic method could also call a method with a Type as method argument. This method can be easily called recursively:

public string Analyze<T>() where T : class, new() 
    {
    return AnalyzeInternally(typeof(T));
    }

private string AnalyzeInternally(Type t)
{
    StringBuilder sb = new StringBuilder();
    var propList = t.GetProperties();
    foreach (var prop in propList)
    {
        System.TypeCode propertyTypeCode = Type.GetTypeCode(prop.PropertyType);

        if (prop.PropertyType.IsClass)
        {
            sb.Append(this.AnalyzeInternally(prop.PropertyType));
        }
        else
        {
            sb.Append("not a class");
        }
    }

    return sb.ToString();
}