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

时间:2014-09-12 15:14:59

标签: 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"

在调试open类型的泛型参数时,我发现它们的FullName为空(以及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

是否有内置的方法来了解某个类型是否已打开?如果没有,有没有更好的方法呢?感谢。

2 个答案:

答案 0 :(得分:12)

您可以使用IsGenericTypeDefinition

typeof(Bar<,>).IsGenericTypeDefinition // true
typeof(Bar<int, string>).IsGenericTypeDefinition // false

答案 1 :(得分:4)

Type.IsGenericTypeDefinition在技术上不是排除开放类型的正确属性。然而,在你的情况下(实际上在大多数其他情况下)它会正常工作。

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

有关详细信息,请参阅此问题的答案:
Difference between Type.IsGenericTypeDefinition and Type.ContainsGenericParameters

TL; DR:后者是递归的,而前者不是,因此可以被欺骗&#34;通过构造具有泛型类型定义的泛型类型作为其至少一个泛型类型参数。