4

I created a class dynamically (found it here) but I don't understand why I cannot use it to create a list?

var myType = CompileResultType();
var myObject = Activator.CreateInstance(myType);
var myList = new List<myObject>();

// Error: The type or namespace name 'myObject' 
// could not be found (are you missing a using directive 
// or an assembly reference?)

How should I do it?

Community
  • 1
  • 1
yonan2236
  • 13,371
  • 33
  • 95
  • 141

5 Answers5

8

They're called generic type parameters, because they expect types, not instances. So you need to know the actual type or create the list object with reflection as well.

Type listType = typeof(List<>);
Type dynamicClassType = listType.MakeGenericType(myObject.GetType());
object myList = Activator.CreateInstance(dynamicClassType);

However, you're unable to use the instance in any meaningful way since it's an object.

  • You could cast it to an IList as suggested in Avner Shahar-Kashtan's answer and use the nongeneric methods.

    IList myList = (IList)Activator.CreateInstance(dynamicClassType);
    
  • You could call the methods of the list-instance through reflection as well.

    // roughly
    MethodInfo addMethod = myList.GetType().GetMethod("Add");
    addMethod.Invoke(myList, objectToAdd);
    
  • Or do as suggested in Cuong Le's answer and use dynamic as the type of the list-instance.

    dynamic myList = Activator.CreateInstance(dynamicClassType);
    
Community
  • 1
  • 1
J. Steen
  • 15,470
  • 15
  • 56
  • 63
6

In order to construct a generic type dynamically, you'll have to use Reflection, and specifically the MakeGenericType method. Something like this:

Type baseListType = typeof(List<>); // get the generic List<>
Type myType = CompileResultType; // same as in yours.
Type myListType = baseListType.MakeGenericType(myType); // Get the List<MyType>
IList myList = (IList)Activator.CreateInstance(myListType); // Instantiate.

Notice that I defined myList as IList, since we don't have a compile-time type for it. Luckily, we have convenient base classes and interfaces like IList, IEnumerable and several others that List<T> implements, which we can use.

Avner Shahar-Kashtan
  • 14,492
  • 3
  • 37
  • 63
2

Generic type need a type of class, not instance, maybe you need:

var myType = CompileResultType();
var listType = typeof (List<>).MakeGenericType(myType);
var myList = Activator.CreateInstance(listType);

But myList in here is object, if you would like to add or remove item in list, you should take advantage of dynamic:

dynamic myList = Activator.CreateInstance(listType);

So you can call:

myList.Add(...);
cuongle
  • 74,024
  • 28
  • 151
  • 206
1

this will create type of list List<WhatEverIsInMyType>:

var listType = typeof(List<>).MakeGenericType(myType);

now you need to create an instance but that you have covered:

var list = Activator.CreateInstance(listType);

Unfortunately we are using reflection so exact types are not known at compile time but not all is lost you can use nongeneric types:

    var list = (IList)Activator.CreateInstance(listType);

now you can use methods like Add Remove to use your list but be careful because you will get runtime exceptions if types don't math.

Rafal
  • 12,391
  • 32
  • 54
0

You work with types, not instances. Assuming CompileResultType() returns MyType:

MyType myType = CompileResultType();
List<MyType> list = new List<MyType>();

I'm not sure why you're using Activator.CreateInstance() though ...

Sameer Singh
  • 1,358
  • 1
  • 19
  • 47