Rn2dy
Rn2dy

Reputation: 4190

How to instantiate a generic type object in C#?

I have class like this:

public ClassA<T> where T : class{
       ...
}

Now I need to to create an object of ClassA in the constructor of ClassB:

public ClassB{
   public ClassA<?> objA;
   public ClassB(string TypeInfo){
       objA = new ClassA<?>(); // Suppose TypeInfo = 'ClassC', and the '?'
                               // Should be derived from TypeInfo
   }
   ...
}

I don't know what to replace '?' for, since the type can only be known at runtime... any ideas?

Upvotes: 1

Views: 577

Answers (4)

Chris Hannon
Chris Hannon

Reputation: 4134

The closest to determining and creating the generic type at runtime that you'll probably get (using a string that represents the type name) is instantiating it like this.

public class ClassB
{
    public ClassB(string typeInfo)
    {
        var typeOfT = Type.GetType(typeInfo);
        var type = typeof(ClassA<>).MakeGenericType(typeOfT);
        var instance = Activator.CreateInstance(type);
    }
}

Exposing that directly through a public field will not be doable unless you mark your field as dynamic, because otherwise it will need that generic type information up front.

public dynamic objA;

Also, the string that represents the type must be qualified enough so that it can be located without ambiguity by Type.GetType(). For example, SomeNamespace.ClassC instead of ClassC.

Upvotes: 10

Default Writer
Default Writer

Reputation: 2566

There is no reason to use generics for the types not known at compile time, because generics is used only for the KNOWN types, which means you can always make a substitution of a generic parameter with a type.

The only matching type in the questioned situation is object type which is a base class for the all object types, and is always known to the compiler.

public ClassB{ 
   public ClassA<object> objA; 
   public ClassB(string TypeInfo){ 
       objA = new ClassA<object>();
   } 
   ... 
} 

About your question...

The only way to use a type not known at compile time is resolve the type at run time, make the ClassB generic, and use ILGenerator() for the generic class A to instantiate of construction of that class at the run-time.

public ClassB<T>{ 
   public ClassA<T> objA; 
   public ClassB(){ 
       objA = new ClassA<T>();
   } 
   ... 
} 

Upvotes: -1

Paul Keister
Paul Keister

Reputation: 13077

Since objA is part of the definition of ClassB, ClassB will have to have to have a type parameter if ClassA has a type parameter, i.e.

public ClassB<T>
{
   public ClassA<T> objA
   ...
}

If the type of objA is not known at compile time it will have to be of type Object or a non-generic base or interface. There's no middle ground.

Upvotes: 0

griegs
griegs

Reputation: 22760

use object o = Activator.CreateInstance(constructed);

this came from MSDN http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx

edit

we use it in extension methods like;

public static object DefaultValue(this Type targetType) { return targetType.IsValueType ? Activator.CreateInstance(targetType) : null; }

It's not a huge stretch to make it work with generics

Upvotes: 0

Related Questions