1

I am trying to get a collection of string that give me the names of the fields of all my class members, separated by .s. For example:

public class Apple
{
    public Banana MyBanana = new Banana();
    public Cranberry MyCranberry = new Cranberry();
}

public class Banana
{
    public int MyNumber = 5;
    public Cranberry MyCranberry = new Cranberry();
}

public class Cranberry
{
    public string MyString = "Hello!";
    public int MyOtherNumber = 10;
}

public class Demo
{
    public List<string> GetFields(Type Apple)
    {
        //I can't figure this out
        //But it should return a list with these elements:
        var result = new List<string>
        {
            "MyBanana.MyNumber",
            "MyBanana.MyCranberry.MyString",
            "MyBanana.MyCranberry.MyOtherNumber",
            "MyCranberry.MyString",
            "MyCranberry.MyOtherNumber"
        };
        return result;
    }
}

I believe some sort of recursion and reflection are required, but after writing dysfunctional code for hours, I need some help.

The reason I need this, is because I am accessing third party code which uses these file paths as the key to their respective values.

An example of one failed attempt:

    private List<string> GetFields(Type type)
    {
        var results = new List<string>();
        var fields = type.GetFields();
        foreach (var field in fields)
        {
            string fieldName = field.Name;
            if (field.ReflectedType.IsValueType)
            {
                results.Add(fieldName);
            }
            else
            {
                results.Add(field.Name + GetFields(field.FieldType));
            }
        }
        return results;
    }

I have found several related questions, but none of them exactly fit my question, and I was unable to make the jump myself: Recursively Get Properties & Child Properties Of A Class, https://stackoverflow.c"om/questions/6196413/how-to-recursively-print-the-values-of-an-objects-properties-using-reflection, Recursively Get Properties & Child Properties Of An Object, .NET, C#, Reflection: list the fields of a field that, itself, has fields

Evorlor
  • 7,263
  • 17
  • 70
  • 141
  • `Apple.GetFields(BindingFlags.Public).ToList();` That will give you a `List`. You can then convert it by getting the field name into the `List` that you need – Frontear Apr 23 '19 at 13:19
  • What is your current results ? You need Reflection (GetFields) to obtain the first level of Properties, then for each, get it's type and use GetField again, recursively. – KiwiJaune Apr 23 '19 at 13:20

1 Answers1

3

You need a recursive implementation:

HashSet<Type> nonRecursiveTypes = new HashSet<Type> { typeof(System.Int32), typeof(System.String) }; // add other simple types here
IEnumerable<string> GetFields(object obj)
{
    foreach (var field in obj.GetType().GetFields())
    {
        if (nonRecursiveTypes.Contains(field.FieldType))
            yield return field.Name;
        else
            foreach (var innerFieldName in GetFields(field.GetValue(obj)))
                yield return field.Name + "." + innerFieldName;
    }
}
Arshia001
  • 1,854
  • 14
  • 19
  • this is the way++ – Mulan Apr 23 '19 at 13:27
  • Works great! Also helped me to uncover a bug with the code which is why all my previous attempts failed. Thank you!! – Evorlor Apr 23 '19 at 13:37
  • Is there any danger to using `if(field.FieldType.IsValueType)` instead of `if(nonRecursiveTypoes.Contains(field.FieldType))`? – Evorlor Apr 23 '19 at 13:52
  • Value types aren't always simple types, structs are also value types. Also, you won't stop on strings, as those are reference types. It really depends on what you want to do, but I don't think it'll work out for your scenario. – Arshia001 Apr 24 '19 at 17:53