Определить, открыт ли универсальный тип?

У меня в сборке куча обычных, закрытых и открытых типов. У меня есть запрос, который я пытаюсь исключить из него открытые типы

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

Есть ли встроенный способ узнать, открыт ли тип? если нет, то есть ли лучший способ сделать это? Спасибо.


person vexe    schedule 12.09.2014    source источник
comment
Вы смотрели документацию для IsGenericType? Use the ContainsGenericParameters property to determine whether a Type object represents an open constructed type or a closed constructed type.   -  person Dark Falcon    schedule 12.09.2014
comment
Вам нужно получить все типы открытого типа?...var types = Assembly.GetExecutingAssembly().GetTypes().Where(t =› !t.IsGenericTypeDefinition);   -  person terrybozzio    schedule 12.09.2014
comment
@Dark Falcon: Спасибо за ваш вклад. Это тоже работает. Я видел ContainsGenericParameters pop в intellisense, но я думал, что он возвращает true, если для типа есть какие-либо общие аргументы. Читая документ, кажется, что «аргумент» - это не то же самое, что «параметр»? @terrybozzio нет, наоборот, отфильтруйте их :)   -  person vexe    schedule 12.09.2014
comment
в моем отредактированном комментарии он их отфильтрует...   -  person terrybozzio    schedule 12.09.2014
comment
@terrybozzio это заметил, спасибо +1 :)   -  person vexe    schedule 12.09.2014


Ответы (2)


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

typeof(Bar<,>).IsGenericTypeDefinition // true
typeof(Bar<int, string>).IsGenericTypeDefinition // false
person Andrew Whitaker    schedule 12.09.2014
comment
Вы можете принять ответ через 2 минуты... ~____~ *продолжает щелкать левой кнопкой мыши - person vexe; 12.09.2014
comment
@vexe: Ха-ха, рад помочь. - person Andrew Whitaker; 12.09.2014
comment
Только что нашел это, похоже, это тоже другой способ IsConstructedGenericType msdn.microsoft.com/en-us/library/ - person vexe; 19.09.2014
comment
@vexe: Похоже, это тоже сработает. Хотя это выглядит как полная противоположность IsGenericTypeDefinition. - person Andrew Whitaker; 19.09.2014

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

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

Полную информацию см. в ответе на этот вопрос:
Разница между Type.IsGenericTypeDefinition и Type.ContainsGenericParameters

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

person AnorZaken    schedule 04.06.2017
comment
Я не уверен, почему ваш ответ не принят. Вопрос явно спрашивает, открыт ли тип. Поскольку эти полуоткрытые типы не могут быть созданы, их определенно нельзя считать закрытыми. В любом случае за этот ответ +1 :) - person Riki; 13.02.2019