2014-09-12 2 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, чтобы определить, является ли объект типа открытым построенным типом или закрытым построенным типом. ' –

+1

Вам нужно получить все типы, которые являются открытым типом? ... var types = Assembly.GetExecutingAssembly(). GetTypes() . Где (t =>! T.IsGenericTypeDefinition); – terrybozzio

+0

@ Dark Falcon: Спасибо за ваш вклад. Это тоже работает. Я видел всплывающее окно ContainsGenericParameters в intellisense, но я думал, что он возвращает true, если есть какие-либо общие аргументы для типа. Кажется, что не так читать документ - кажется, что «аргумент» не совпадает с «параметром»? @terrybozzio no, напротив, отфильтровать их :) – vexe

ответ

10

Вы можете использовать IsGenericTypeDefinition:

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

«Вы можете принять ответ за 2 минуты. .. "~ ____ ~ * продолжает трещать левой кнопкой мыши – vexe

+0

@vexe: Ха-ха, рад помочь. –

+0

Просто нашел это, похоже, еще один способ IsConstructedGenericType http://msdn.microsoft.com/en-us/library/system.type.isconstructedgenerictype%28v=vs.110%29.aspx – vexe

2

Type.IsGenericTypeDefinition не является технически правильным свойство, чтобы исключить открытые типы. Однако в вашем случае это будет очень хорошо (и даже в большинстве других случаев).

Это, как говорится, тип может быть открытым без определения общего типа. В более общем случае, например, в общедоступном методе, который принимает параметр типа, то, что вы действительно хотите, это Type.ContainsGenericParameters.

Для получения подробной информации смотрите ответ на этот вопрос:
Difference between Type.IsGenericTypeDefinition and Type.ContainsGenericParameters

TL; DR: Последнее является рекурсивным, в то время как бывший не является, и таким образом, может быть «обмануть» путем построения универсального типа, который имеет определение общего типа как по крайней мере один из его параметров типового типа.

Смежные вопросы