【问题标题】:C# How to Initialize Generic class with object of type "Type"C#如何使用“Type”类型的对象初始化泛型类
【发布时间】:2013-10-04 06:04:55
【问题描述】:

我最近遇到了这个问题。

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 的工作方式有些困惑。无论如何,感谢您的帮助。

谢谢。

【问题讨论】:

    标签: c# generics reflection typeof gettype


    【解决方案1】:

    你想要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>();
    

    【讨论】:

    • 谢谢,我以为有更清洁的解决方案,但我想没有。
    • @RayL:不,泛型在反射方面很棘手——它们基本上是为在编译时知道类型参数而设计的。
    • @RayL:也请阅读 cdhowie 的答案 - 您提供的所有示例都是在编译时已知类型参数的地方。真的是这样吗?如果是这样,请使用通用方法。
    【解决方案2】:

    像这样:

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

    【讨论】:

    • 谢谢,不知道该把谁标记为这个答案,但人们似乎更喜欢 skeets 的答案。对不起,你不得不和他竞争:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-06
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    相关资源
    最近更新 更多