检测泛型类型是否已打开?

vex*_*exe 4 c# reflection generic-type-argument

我的程序集中有一堆常规,封闭和打开的类型.我有一个查询,我试图排除它的开放类型

class Foo { } // a regular type
class Bar<T, U> { } // an open type
class Moo : Bar<int, string> { } // a closed type

var types = Assembly.GetExecutingAssembly().GetTypes().Where(t => ???);
types.Foreach(t => ConsoleWriteLine(t.Name)); // should *not* output "Bar`2"
Run Code Online (Sandbox Code Playgroud)

在调试open类型的泛型参数时,我发现它们FullName是null(以及其他类似的东西DeclaringMethod) - 所以这可能是一种方式:

    bool IsOpenType(Type type)
    {
        if (!type.IsGenericType)
            return false;
        var args = type.GetGenericArguments();
        return args[0].FullName == null;
    }

    Console.WriteLine(IsOpenType(typeof(Bar<,>)));            // true
    Console.WriteLine(IsOpenType(typeof(Bar<int, string>)));  // false
Run Code Online (Sandbox Code Playgroud)

有没有内置的方法来知道类型是否打开?如果没有,有没有更好的方法呢?谢谢.

And*_*ker 12

你可以使用IsGenericTypeDefinition:

typeof(Bar<,>).IsGenericTypeDefinition // true
typeof(Bar<int, string>).IsGenericTypeDefinition // false
Run Code Online (Sandbox Code Playgroud)


Ano*_*ken 10

Type.IsGenericTypeDefinition在技​​术上不是排除开放类型的正确属性。但是,它在您的情况下(实际上在大多数其他情况下)都可以正常工作。

也就是说,一个类型可以是开放的,而不是一个泛型类型定义。在更一般的情况下,例如在接受 Type 参数的公共方法中,您真正想要的是Type.ContainsGenericParameters

有关完整详细信息,请参阅此问题的答案:
Type.IsGenericTypeDefinition 和 Type.ContainsGenericParameters 之间的差异

TL;DR:后者是递归的,而前者不是,因此可以通过构造具有泛型类型定义作为其泛型类型参数中的至少一个的泛型类型来“愚弄”。