C# How to Initialize Generic class with object of type "Type"

12,679

Solution 1

You want Type.MakeGenericType and then Activator.CreateInstance... but then calling a method on the newly-created object will be tricky. Ideally you could have a non-generic base class or interface containing those members:

public interface IFoo
{
    void CallSomeMethod();
}

public class MyGenericClass<T> : IFoo
{
    ...
}

// Names changed to be more conventional
public void DoSomething(Type type)
{
    var genericType = typeof(MyGenericClass<>).MakeGenericType(type);
    var instance = (IFoo) Activator.CreateInstance(genericType);
    instance.CallSomeMethod();
}

If you do need to call a method which depends on the type parameter, you'll need to do that with reflection, or with dynamic which can streamline reflection-based code.

EDIT: As cdhowie says, if you always actually do know the type at compile-time, you can use a generic method which would make things much simpler. You'd then call the method like this:

DoSomething<int>();
DoSomething<MyClassA>();
DoSomething<MyClassB>();

Solution 2

Like this:

object myGenObj = Activator.CreateInstance(typeof(MyGenericClass<>).MakeGenericType(_type));

However, since the produced object is of a type that you don't know at compile-time, you can't really invoke members of the object through the generic type (except via reflection). If there is an ancestor type or implemented interface that you do know of at compile-time, you can cast to that and then invoke the member.

You might also consider wrapping this functionality in a generic method, which makes the whole thing easier to deal with:

public void doSomething<T>()
{
    var myGenObj = new MyGenericClass<T>();
    myGenObj.doSomeGenStuff();
}

If you have to support Type objects you can use an overload that cheats using reflection:

public void doSomething(Type _type)
{
    this.GetType().GetMethod("doSomething", Type.EmptyTypes)
        .MakeGenericMethod(_type)
        .Invoke(this, null);
}
Share:
12,679
RayLoveless
Author by

RayLoveless

Software Engineer in the beautiful state of Utah. Happy trails :). If you want to contact me I use my stack overflow username @gmail.com.

Updated on July 26, 2022

Comments

  • RayLoveless
    RayLoveless almost 2 years

    I recently had this problem.

    doSomething(typeof(int));
    doSomething(typeof(MyClassA));
    doSomething(typeof(MyClassB));
    
    public void doSomething(Type _type)
    {
        var myGenObj = new MyGenericClass<_type>();  // Error.  Really I'd want MyGenericClass<int>, MyGenericClass<MyClassA>, etc depending on what's passed in.
        myGenObj.doSomeGenStuff();
        // more stuff...
    
    }
    

    I think that this can be done with reflection somehow.. Possibly there's an easier way. I've been somewhat confused on how Type works vs Classes under the covers. Anyways thanks for any help.

    Thanks.

  • RayLoveless
    RayLoveless over 10 years
    Thanks, Thought there was a cleaner solution but I guess not.
  • Jon Skeet
    Jon Skeet over 10 years
    @RayL: No, generics are tricky with reflection - they're basically designed for when the type arguments are known at compile-time.
  • RayLoveless
    RayLoveless over 10 years
    Thanks, Wasn't sure who to mark as answer on this one but people seemed to like skeets answer a bit more. Sorry you had to compete with him :)
  • Jon Skeet
    Jon Skeet over 10 years
    @RayL: Read cdhowie's answer as well - all the samples you've given are where the type argument is known at compile-time. Is that actually the case? If so, use a generic method.