2014-09-12 140 views
3

我在我的程序集中有一堆常规,封闭和打开的类型。我有一个查询,我试图从它检测泛型类型是否打开?

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" 

排除开放类型在调试一个开放型的通用参数,我发现他们的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 

是否有内置的方式来知道类型是否打开?如果没有,是否有更好的方法来做到这一点?谢谢。

+1

你看过“IsGenericType”的文档吗?使用ContainsGenericParameters属性来确定Type对象是表示一个打开的构造类型还是一个封闭的构造类型。' – 2014-09-12 15:19:37

+1

您需要获取所有打开类型的类型?var types = Assembly.GetExecutingAssembly()。GetTypes() .Where(t =>!t.IsGenericTypeDefinition); – terrybozzio 2014-09-12 15:25:07

+0

@Dark Falcon:谢谢你的输入。这也适用。我在intellisense中看到过'ContainsGenericParameters'弹出,但如果有类型的任何泛型参数,我认为它会返回true。似乎没有阅读文档 - 似乎'参数'与'参数'不一样? @terrybozzio不,相反,过滤出来:) – vexe 2014-09-12 15:25:29

回答

10

你可以使用IsGenericTypeDefinition

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

“你可以在2分钟内接受答案。 ..“〜____〜*继续猛击左键点击 – vexe 2014-09-12 15:28:19

+0

@vexe:哈哈,很乐意帮忙。 – 2014-09-12 15:30:09

+0

刚刚发现这个,似乎是另一种方式IsConstructedGenericType http://msdn.microsoft.com/en-us/library/system.type.isconstructedgenerictype%28v=vs.110%29.aspx – vexe 2014-09-19 15:12:12

2

Type.IsGenericTypeDefinition在技术上并不排除开放类型正确的属性。然而,它会在你的情况下工作得很好(事实上在大多数情况下)。

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

有关详情请参阅回答这个问题:
Difference between Type.IsGenericTypeDefinition and Type.ContainsGenericParameters

TL; DR:后者是递归的,而前者不是,通过构建具有泛型类型因此可以“上当”泛型类型定义至少是其一个泛型类型参数。

相关问题