-1

I got a Big hierarchic class that i would like to loop all it's properties and sub properties etc..

Example

public class RootClass
{
   // properties ..
   List<Item> FirstItemsList { get; set;}
   List<Item> SecondItemsList { get; set;}
   SubClass SubClass { get; set;}
}
public class SubClass
{
   // properties ..
   List<Item> ThirdItemsList { get; set;}
}
public class Item
{
   //properties 
}

i want a function that will return me a list of all Item type found i.e

public IList<Item> GetAllItemsInClass(RootClass entity);

Thanks

ibm123
  • 1,214
  • 2
  • 15
  • 39
  • possible duplicate of [Reflection class to get all properties of any object](http://stackoverflow.com/questions/4020041/reflection-class-to-get-all-properties-of-any-object) – Preet Sangha Jan 02 '12 at 11:08
  • I tried to use this code http://stackoverflow.com/questions/721441/c-sharp-how-to-iterate-through-classes-fields-and-set-properties but didn't know how to modify it – ibm123 Jan 02 '12 at 11:19
  • @ibm123 - Can you provide an example of the output you expect to see? Using reflection it is trivial to get the properties of any specific class (and the properties of any class represented by its properties) but it is difficult to answer without seeing *how* you would like them reported. – M.Babcock Jan 04 '12 at 04:43

1 Answers1

0

If you need something that would work in a general case (any class hierarchy) then you could do the following:

You will need a recursive algorithm (function). The algorithm would loop over the members, adding their types to a list (if they're not already added) and then returning that list, COMBINED with the types of the members of the type just added to the list-here you make the recursive call. The terminating conditions would be:

  1. The type of a member is a primitive (to check this use Type.IsPrimitive).
  2. The type being reflected is defined in another assembly. You can check the defining assembly using Type.Assembly.

If you need something simpler, then use the technique above but just use an if statement in the loop.

Let me know if this is what you want or no and then I will post a code sample for you when I have more time.

Update: The following is a code sample showing how you can process a type and recursively get all the types contained within it. You can call it this way: List typesHere = GetTypes(myObject.GetType())

    public static List<Type> GetTypes(Type t)
    {
        List<Type> list = new List<Type>();
        if (t.IsPrimitive)
        {
            if (!list.Contains(t))
                list.Add(t);
            return list;
        }
        else if (!t.Assembly.Equals(System.Reflection.Assembly.GetExecutingAssembly()))
        {
            //if the type is defined in another assembly then we will check its
            //generic parameters. This handles the List<Item> case.
            var genArgs = t.GetGenericArguments();
            if (genArgs != null)
                foreach (Type genericArgumentType in genArgs)
                {
                    if(!list.Contains(genericArgumentType))
                        list.AddRange(GetTypes(genericArgumentType));
                }
            return list;
        }
        else
        {
            //get types of props and gen args
            var types = t.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Select(pi => pi.PropertyType).ToList();
            types.AddRange(t.GetGenericArguments());
            foreach (System.Type innerType in types)
            {
                //get the object represented by the property to traverse the types in it.
                if (!list.Contains(innerType))
                    list.Add(innerType);
                else continue; //because the type has been already added and as thus its child types also has been already added.

                var innerInnerTypes = GetTypes(innerType);
                //add the types filtering duplicates
                foreach (Type t1 in innerInnerTypes) //list.AddRange(innerTypes); //without filtering duplicates.
                    if (!list.Contains(t1))
                        list.Add(t1);
            }
            return list;
        }
    }

So when I ran this on the classes you posted in your original post (Item having two primitive properties like below) I got the following list:

GetTypes(typeof(List<Item>))
Count = 3
    [0]: {Name = "Item" FullName = "AssemblyNameXYZ.Item"}
    [1]: {Name = "String" FullName = "System.String"}
    [2]: {Name = "Int32" FullName = "System.Int32"}

GetTypes(typeof(Item))
Count = 2
    [0]: {Name = "String" FullName = "System.String"}
    [1]: {Name = "Int32" FullName = "System.Int32"}

Reflection.GetTypes(typeof(RootClass))
Count = 5
    [0]: {Name = "List`1" FullName = "System.Collections.Generic.List`1[[AssemblyNameXYZ.Item, AssemblyNameXYZ, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}
    [1]: {Name = "Item" FullName = "AssemblyNameXYZ.Item"}
    [2]: {Name = "String" FullName = "System.String"}
    [3]: {Name = "Int32" FullName = "System.Int32"}
    [4]: {Name = "SubClass" FullName = "AssemblyNameXYZ.SubClass"}

I didn't make comprehensive tests but this should at least point you to the right direction. Fun question. I have fun answering.

Lzh
  • 3,585
  • 1
  • 22
  • 36
  • I have an exam now. Right after I'll be more than motivated to post a code sample! See you in 3-4 hours :) – Lzh Jan 04 '12 at 11:41