Search code examples
c#linqconsole-applicationpropertyinfo

Get all values of List with its nested list properties


This morning i came uppon which seemed a simple problem to solve. I wanted to write all values of a list into my console. In this case, the List contains List Members. I've been searching for a solution for some time now but I couldn't find one.

I've made it so far.

tl.ForEach(tradelane =>
        {
            row = "";

            foreach(PropertyInfo pi in typeof(coTradeLane).GetProperties())
            {
                Type T = pi.PropertyType;

                if (T.IsGenericType && T.GetGenericTypeDefinition() == typeof(List<>))
                {
                    foreach(PropertyInfo piList in tradelane.GetType().GetProperties())
                    {

                            // Select the nested list and loop through each member..

                    }
                    continue;
                }

                var val = pi.GetValue(tradelane);
                if (val != null) row += val.ToString() + " \t ";
                else row += " \t \t ";
            }
            Console.WriteLine(row);
        });

Solution

  • I'm not entirely sure what you want, but this recursive solution may help you on your way. I have cheated slightly because I'm looking for IList rather than List<T> to simplify the code.

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace Demo
    {
        // This type contains two properties.
        // One is a plain List<Double>, the other is a type that itself contains Lists.
    
        public sealed class Container
        {
            public List<double> Doubles { get; set; }
    
            public Lists Lists { get; set; }
        }
    
        // This type contains two Lists.
    
        public sealed class Lists
        {
            public List<string> Strings { get; set; }
            public List<int> Ints { get; set; }
        }
    
        public static class Program
        {
            private static void Main()
            {
                var lists = new Lists
                {
                    Strings = new List<string> {"A", "B", "C"}, 
                    Ints = new List<int> {1, 2, 3, 4, 5}
                };
    
                var container = new Container
                {
                    Doubles = new List<double> {1.1, 2.2, 3.3, 4.4},
                    Lists = lists
                };
    
                var items = FlattenLists(container);
    
                // This prints:
                //
                // 1.1
                // 2.2
                // 3.3
                // 4.4
                // A
                // B
                // C
                // 1
                // 2
                // 3
                // 4
                // 5
    
                foreach (var item in items)
                    Console.WriteLine(item);
            }
    
            // This recursively looks for all IList properties in the specified object and its subproperties.
            // It returns each element of any IList that it finds.
    
            public static IEnumerable<object> FlattenLists(object container)
            {
                foreach (var pi in container.GetType().GetProperties().Where(p => p.GetMethod.GetParameters().Length == 0))
                {
                    var prop = pi.GetValue(container);
    
                    if (typeof(IList).IsAssignableFrom(pi.PropertyType))
                    {
                        foreach (var item in (IList) prop)
                            yield return item;
                    }
    
                    foreach (var item in FlattenLists(prop))
                        yield return item;
                }
            }
        }
    }
    

    I'm not sure how much use this is though, since you just get a flattened list of object with no idea of the property with which they are associated. You could, however, modify FlattenLists() to return more information than just the object.