C#如何使用“Type”类型的对象初始化Generic类

时间:2013-09-27 20:10:42

标签: c# generics reflection typeof gettype

我最近遇到了这个问题。

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...

}

我认为这可以通过某种方式进行反思。可能有一种更简单的方法。关于Type的工作方式和类下的Classes,我有点困惑。无论如何,谢谢你的帮助。

感谢。

2 个答案:

答案 0 :(得分:7)

您想要Type.MakeGenericType然后Activator.CreateInstance ...但是然后在新创建的对象上调用方法将会非常棘手。理想情况下,您可以拥有一个非泛型基类或包含这些成员的接口:

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

如果你需要调用一个取决于类型参数的方法,你需要使用带有dynamic的反射,进行调用。可以简化基于反射的代码。

编辑:正如cdhowie所说,如果你总是在编译时知道类型,你可以使用一个通用方法,这会使事情变得更简单。然后你调用这样的方法:

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

答案 1 :(得分:4)

像这样:

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

但是,由于生成的对象是您在编译时不知道的类型,因此无法通过泛型类型(通过反射除外)实际调用对象的成员。如果您在编译时 知道有祖先类型或已实现的接口,则可以转换为该接口,然后调用该成员。

您可能还会考虑将此功能包装在一个通用方法中,这使整个过程更容易处理:

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

如果你必须支持Type个对象,你可以使用反射欺骗的重载:

public void doSomething(Type _type)
{
    this.GetType().GetMethod("doSomething", Type.EmptyTypes)
        .MakeGenericMethod(_type)
        .Invoke(this, null);
}