获取“”的类型;递归泛型”;

本文关键字:递归 泛型 获取 类型 | 更新日期: 2023-09-27 17:58:25

我确实有一个类,它被定义为:

public abstract class Singleton <T> : BaseObject
    where T : Singleton <T>
{
}

我想在其他地方定义一个这些泛型singleton的数组。类似的东西

public MonoSingleton[] singletons;

如何检索该泛型的正确类型(如您所见,它似乎是递归的)?我该怎么写?

获取“”的类型;递归泛型”;

你想做这样的"奇怪的递归模板模式"吗?

class CuriouslyRecursiveBase<T>
{
}
class CuriouslyRecursiveDervied<T> : CuriouslyRecursiveBase<T>
{
}
class MyClass : CuriouslyRecursiveBase<MyClass>
{
}

要实例化从基础派生的,只需使用:

class CuriouslyRecursiveBase<T>
{
    public static void InstantiateDerived()
    {
        T instance = (T)Activator.CreateInstance(typeof(T));
    }
}

由于T实际上是派生类型(MyClass),并且奇怪地也是类型(CuriouslyRecursive<MyClass>)。

具体应用于您的问题:

// Create a common interface that all singletons use. This allows 
// us to add them all to a list.
interface ISingleton { }
class Singleton<T> : ISingleton
{
    // Store our list of ISingletons
    static List<ISingleton> instances = new List<ISingleton>();
    static T instance;
    protected Singleton() { }
    public static T GetInstance()
    {
        // Either return the existing instnace, or create a new one
        if (Singleton<T>.instance == null)
        {
            Singleton<T>.instance = (T)Activator.CreateInstance(typeof(T));
            // Use a common interface so they can all be stored together.
            // Avoids the previously mentioned co-variance problem.
            // Also, compiler isn't built to follow curious recursiveness,
            // so use a dynamic statement to force runtime re-evaluation of 
            // the type hierarchy. Try to avoid dynamic statements in general
            // but in this case its useful.
            instances.Add((dynamic)Singleton<T>.instance);
        }
        return Singleton<T>.instance;
    }
}
class MyClass : Singleton<MyClass>
{
}
public static void Main()
{
    MyClass my = MyClass.GetInstance();
}

更多信息:

http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

使用设计时代码,您将能够通过使用typeof运算符并为泛型参数提供一些参数来获得类型:

typeof(Singleton<SomeImplementationOfBaseObject>)

typeof(Singleton<>)

但也有另一种选择:反思。

Type singletonType = Type.GetType("NamespaceA.NamespaceN.Singleton`1");

第1部分是通用参数的数量。如果你有类似Class<T, S>的东西,它应该是2,依此类推

请注意,使用反射,您不需要给出泛型参数。无论如何,您都可以使用泛型参数获取类型。为了给出通用的论点,你可以这样做:

Type genericType = singletonType.MakeGenericType(typeof(SomeImplementationOfBaseObject));

或者,如果你想直接获得它,你可以这样做:

Type singletonType = Type.GetType("NamespaceA.NamespaceN.Singleton`1[[NamespaceA.NamespaceN.SomeImplementationOfBaseObject]]");

[[ ]]中的字符串是作为泛型参数传递的类型的全名。请注意,如果泛型类型与执行类型不是同一个程序集,则需要提供程序集限定名(,例如"NamespaceA.MyClass,MyAssembly")。

更新

OP在一些评论中说:

如果我确实使用:public Singleton<BaseObject>[] singletons;,它警告我带有:"error CS0309:类型BaseObject"必须可转换为Singleton",以便将其用作通用类型或方法"Singleton"

这是另一个问题:不能在类中执行协方差。要做这样的事情,你需要一个这样的界面:

public interface ISingleton<out TBaseObject> where TBaseObject : .........

并使Singleton<T>类实现

因此,您可以通过以下方式创建这样的数组:

public ISingleton<BaseObject>[] singletons;

Covariance允许您上传通用参数,并且仅限于接口和委托。

点击此处了解更多信息:

  • http://msdn.microsoft.com/en-us/library/ee207183.aspx