简体   繁体   English

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

[英]C# How to Initialize Generic class with object of type “Type”

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. 关于Type的工作方式和类下的Classes,我有点困惑。 Anyways thanks for any help. 无论如何,谢谢你的帮助。

Thanks. 谢谢。

You want Type.MakeGenericType and then Activator.CreateInstance ... but then calling a method on the newly-created object will be tricky. 你想要Type.MakeGenericType然后是Activator.CreateInstance ...但是然后在新创建的对象上调用方法将是棘手的。 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. 如果您确实需要调用依赖于类型参数的方法,则需要使用反射使用dynamic来调整基于反射的代码。

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. 编辑:正如cdhowie所说,如果你总是在编译时确实知道类型,你可以使用一个通用的方法,这将使事情变得更简单。 You'd then call the method like this: 然后你会调用这样的方法:

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

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: 如果必须支持Type对象,则可以使用使用反射作弊的重载:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM