Pergunta

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.

Foi útil?

Solução

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>();

Outras dicas

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);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top