Reflection, Activator.CreateInstance, array<T>

In a generic filer class which knows nothing about the calling assembly's data structures except through reflection, I need to create an instance of a List<T>. I can create simple instances (ints, strings, class instances etc) but not arrays, for two reasons:
1. I can use Assembly.GetType(typeName) to get a Type but if the calling assembly's property is defined as List<ofSomething> then the PropertyInfo.PropertyType.Name is "List`1" - not something nice like TheNameOfMyClass.
2. This might not actually be a problem but since I can't solve #1, I have no idea whether this works! I create an instance using Activator.CreateInstance(objType, numItems). Is this correct to initialise a collection to a known number of elements before later calling pinfo.SetValue(item, reference, index)?
Code used to create list:
Type objType = assembly.GetType(assembly.GetName().Name + "." + pinfo.PropertyType.Name, true);
object objInstance = Activator.CreateInstance(objType, numItems);

assembly - Assembly in which to look for type name
pinfo - PropertyInfo of the property
numItems - size of the array/collection

Example class being populated by reflection:
class MyClass
  public string TestString;
  public int TestInt;
  public bool TestBool;
  public List<string> TestList;
The string/int/bool work fine (different code from above) but the list doesn't. I can't change the List<string> definition.

Open in new window

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

gmayoAuthor Commented:
Actually I can get that to work if the list is declared as a "proper" class, ie:
class MyList : List<MyType>

I'd still like to solve problem #1 if I can though.

However, I now have a problem adding items to that list:

objInstance[idx++] = childInstance;
// obviously doesn't work because objInstance is of type object.

(object[])objInstance[idx++] = childInstance;
// also doesn't work - runtime error casting from object[] to List<MyType>

(List<object>)objInstance[idx++] = childInstance;
// also doesn't work for the same reason. I'm out of ideas now!

Open in new window

@2 : if you create a list with the number of items constructor, you're not actually creating the items, but only reserving that amount of memory.

if you want to do something with the list, but you have problems accessing its members, do something like:
object objInstance = Activator.CreateInstance(objType, numItems);  // your code

IList myList = objInstance as IList;

if (myList != null)
   myList.Add(childinstance); // add the child item

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial

I'm not sure i fully understand what you're doing in your question, however it appears you're having difficulty creating a generic collection driven by some reflection activities? It might help to use the MakeGenericMethod which allows you to interact with your collection exactly as you'd want to but to provide the type parameter dynamically.

I've put together a short code example, it's fairly dirty stuff, but it illustrates the idea, all be it with some undesireable string handling to retrieve the collection's 'collected' type.


public class AnotherClass
            public int MyNumber { get; set; }

        public class MyClass
            public int TestInt;
            public bool TestBool;
            public List<AnotherClass> TestList;

        private void Populate()
            Type theType = typeof(MyClass);
            FieldInfo[] fields = theType.GetFields();
            object myObj = Activator.CreateInstance(theType);

            foreach (FieldInfo fi in fields)
                if (fi.FieldType.Name == "List`1")
                    string s = fi.FieldType.AssemblyQualifiedName;
                    s = s.Replace("System.Collections.Generic.List`1[[", string.Empty);
                    s = s.Substring(0, s.IndexOf("]"));

                    Type listType = Type.GetType(s);
                    MethodInfo mi = this.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)
                                                    .Where(m => m.IsGenericMethod && m.Name.StartsWith("BuildList")).First();

                    mi = mi.MakeGenericMethod(new Type[] { listType });
                    object theList = mi.Invoke(this, new object[0]);

                    fi.SetValue(myObj, theList);
                    fi.SetValue(myObj, Activator.CreateInstance(fi.FieldType));

        private List<T> BuildList<T>() 
            int numOfObjects = 5;
            List<T> mList = new List<T>();

            for (int iLoop = 0; iLoop < numOfObjects; iLoop++)
                mList.Add((T)Activator.CreateInstance(typeof(T), null));

            return mList;

Open in new window

gmayoAuthor Commented:
Thanks - I'm aware I was only reserving space in the array, not actually creating the contents. My intention was to set each index, rather than Add()ing items, and specifying the size first was the idea to avoid out of range exceptions. However, that was flawed anyway.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.