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

Nic*_*yle 10 .net generics clr

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

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

Foo`1[T]
Run Code Online (Sandbox Code Playgroud)

我正在寻找封闭式:

Foo`1[System.Int32]
Run Code Online (Sandbox Code Playgroud)

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

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

我也尝试通过泛型参数找到所有类型,以期发现封闭类型.

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Iva*_*tev 5

据我可以在这种情况下理解Foo<T>是一个开放的未结合的通用的类型,所以在运行时CLR将使用它作为蓝图/骨架构建和关闭通用类型与指定的类型的参数类型(Foo<int>,Foo<object>等).所以基本上Foo<int>是运行时构造的Foo<T>骨架实现.

现在,在运行时你可以Foo<int>通过使用typeof(Foo<int>)或者得到它的类型,typeof(Foo<>).MakeGenericType(new[] { typeof(int) })它不是一样的Type,它就没有意义.但仔细观察,您将看到两者typeof(Foo<T>)typeof(Foo<int>)共享相同的元数据标记和GUID.

另一件有趣的事情就是typeof(Foo<int>).Assembly你会期望的,但正如你已经注意到的那样,你无法从大会中获得这种类型.

那是因为Foo<int>未在程序集中定义(您可以使用Reflector/ILSpy检查程序集元数据).在运行时,CLR将创建("构造")Foo<T>for 的专用("封闭")版本Foo<int>(如此构造的闭合类型的无界开放泛型类型定义)并"给"它a Type.因此,除非CLR以某种方式直接暴露它在运行时生成的封闭泛型类型列表,否则你运气不好.

这里还有一个片段,可能会证实我在说什么:

尽管泛型类型的每个构造(例如Node <Form>和Node <String>)都有自己的不同类型标识,但CLR能够在类型实例化之间重用大部分实际的JIT编译代码.这大大减少了代码膨胀,并且是可能的,因为泛型类型的各种实例在运行时被扩展.编译时构造类型的所有内容都是类型引用.当程序集A和B都引用第三个程序集中定义的泛型类型时,它们的构造类型在运行时进行扩展.这意味着,除了共享CLR类型标识(适当时)之外,从程序集A和B中键入实例化还可以共享运行时资源,例如本机代码和扩展元数据.

http://msdn.microsoft.com/en-us/magazine/cc163683.aspx

  • 这是一些沉重的"运行时CLR魔术":Foo <T>的静态构造函数被调用为每个封闭类型"loading":-) PS当你需要他时,Skeet在哪里? (2认同)