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

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

本文介绍了列出运行时从开放泛型类型创建的封闭类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我列出当前AppDomain中的所有类型时,我会看到具有泛型占位符的泛型类型。然而,如果我用一个类型实例化我的泛型类型,然后列出appDomain中的所有类型,我没有看到新创建的闭合类型。



在示例中下面,输出只是:

pre $ f $ f $ f
code $

 

我正在寻找关闭的类型:

  Foo `1 [System.Int32] 

有没有办法查看运行时创建的封闭类型对我来说,基于我的开放泛型类型?

  class Foo< T> 
{
}

类程序
{
static void Main(string [] args)
{
var tmp =新的Foo< int>();
ListTypes();


从类中的程序集中获取AppDomain.CurrentDomain.GetAssemblies()中的程序集中的类型var b =




$ b $ GetTypes()
其中type.Name.Contains(Foo)
选择类型;

foreach(var类型)
Console.WriteLine(type.ToString());
}
}

我也尝试通过泛型参数找到所有类型希望发现封闭类型。

  class Foo< T> 
{
}

class Bar
{
}

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


从类中的程序集中获取AppDomain.CurrentDomain.GetAssemblies()中的程序集中的类型var b =




$ b $ GetTypes()
其中type.IsGenericType
&&类型.GetGenericArguments()。包含(typeof(Bar))
选择类型;

foreach(var类型)
Console.WriteLine(type.ToString());
}
}

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

解决方案

据我所知,在这种情况下 Foo< T> code>是一个开放的未绑定泛型类型,因此在运行时,CLR将使用它作为蓝图/框架来构造和关闭泛型类型,并指定类型参数类型( Foo / code>, Foo< object> 等)。所以基本上 Foo< int> 是 Foo< T> 骨架的运行时构建实现。



现在,在运行时,可以通过使用 typeof()来获取 Foo 类型Foo< int>)或 typeof(Foo>)MakeGenericType(new [] {typeof(int)})同样的键入并且它没有任何意义。但仔细观察,你会看到 typeof(Foo )和 typeof(Foo< int>)共享相同的元数据令牌和GUID。

另一个有趣的地方是 typeof(Foo< int>)。Assembly 将会是你期望的,但正如你已经注意到,你不能从大会得到这种类型。因为 Foo 未在程序集中定义(您可以使用Reflector / ILSpy)。在运行时,CLR将为 Foo 创建(构建) Foo 的专用(关闭 ; (如此 - 构造一个无界的开放泛型类型定义的封闭类型)并给它一个 Type 。所以除非CLR直接以某种方式公开它在运行时产生的封闭泛型类型列表,否则你是不幸的。



另外这里有一个片段可以证实我我说:


When I list all the types in the current AppDomain, I see my generic types with the generic placeholders. However, if I instantiate my generic types with a type and then list all the types in the appDomain, I don't see the newly created closed types.

In the example below, the output is only:

Foo`1[T]

I'm looking for the closed type:

Foo`1[System.Int32]

Is there a way to see the closed types that the runtime has created for me based on my open generic types?

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

I have also tried finding all types by the generic argument in hopes of discovering the closed type.

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

This is just to satisfy my curiosity.

解决方案

As far as I can understand in this case Foo<T> is an open unbound generic type, so at runtime the CLR will use it as a blueprint/skeleton to construct and close a generic type with the type parameter type specified (Foo<int>, Foo<object>, etc.). So basically Foo<int> is a runtime constructed implementation of the Foo<T> skeleton.

Now, at run-time you can get the type of Foo<int> either by using typeof(Foo<int>) or typeof(Foo<>).MakeGenericType(new[] { typeof(int) }) and it's not the same Type and it wouldn't make sense for it to be. But look closer and you will see that both typeof(Foo<T>) and typeof(Foo<int>) share the same metadata token and GUID.

Another interesting thing is that typeof(Foo<int>).Assembly will be what you would expect, but as you've noticed already you can't get that type from the Assembly.

That's because Foo<int> is not defined in the assembly (you can check the assembly metadata with Reflector/ILSpy). At run-time the CLR will create ("construct") a specialized ("closed") version of the Foo<T> for Foo<int> (so - constructed closed type of an unbounded open generic type definition) and "give" it a Type. So unless the CLR exposes directly somehow the list of closed generic types it generates at run-time you are out of luck.

Also here is a snippet that might confirm what I am saying:

这篇关于列出运行时从开放泛型类型创建的封闭类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 05:53