列出运行时从开放泛型类型创建的已关闭类型

时间:2012-10-10 20:33:04

标签: .net generics clr

当我列出当前AppDomain中的所有类型时,我会看到带有通用占位符的泛型类型。但是,如果我使用类型实例化我的泛型类型然后列出appDomain中的所有类型,我看不到新创建的封闭类型。

在下面的示例中,输出仅为:

Foo`1[T]

我正在寻找封闭式:

Foo`1[System.Int32]

有没有办法根据我的开放泛型类型查看运行时为我创建的封闭类型?

class Foo<T>
{
}

class Program
{
    static void Main(string[] args)
    {
        var tmp = new Foo<int>();
        ListTypes();
    }

    private static void ListTypes()
    {
        var types = from assembly in AppDomain.CurrentDomain.GetAssemblies()
                        from type in assembly.GetTypes()
                        where type.Name.Contains("Foo")
                        select type;

        foreach (var type in types)
            Console.WriteLine(type.ToString());
    }
}

我还尝试通过泛型参数查找所有类型,以期发现封闭类型。

class Foo<T>
{
}

class Bar
{
}

class Program
{
    static void Main(string[] args)
    {
        var tmp = new Foo<Bar>();
        ListTypes();
    }

    private static void ListTypes()
    {
        var types = from assembly in AppDomain.CurrentDomain.GetAssemblies()
                        from type in assembly.GetTypes()
                        where type.IsGenericType
                        && type.GetGenericArguments().Contains(typeof(Bar))
                        select type;

        foreach (var type in types)
            Console.WriteLine(type.ToString());
    }
}

这只是为了满足我的好奇心。

1 个答案:

答案 0 :(得分:1)

Ivan的答案大多是正确的,但声称程序集元数据不包含任何有关构造类型的信息并不完全正确。所有构造的类型都在使用它们的程序集中定义,而 Mono.Cecil 等工具让您可以看到它。构造的类型不会通过反射暴露,甚至Mono.Cecil也很难找到它们。

基本上,您必须遍历程序集中使用的所有类型,例如:属性类型,返回类型,局部变量类型等。此信息包含在程序集元数据中,并且使用Mono.Cecil相当容易枚举。然后只应用简单的过滤器来检测是否构造了类型。请注意,您可能需要遍历几个引用泛型类型定义的程序集,以便查找从中构造的所有类型。

此解决方案有两个限制。首先,通过反射构造的类型自然不会出现在任何组件中。其次,一些构造类型嵌入在泛型类型/方法中,并且只有在使用特定泛型类型参数实例化其父类型/方法之后,才能知道它们的泛型类型参数。