Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect if a generic type is open?

I have a bunch of regular, closed and opened types in my assembly. I have a query that I'm trying to rule out the open types from it

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"

Upon debugging the generic arguments of an open type, I found that their FullName is null (as well as other things like the DeclaringMethod) - So this could be one way:

    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

Is there a built-in way to know if a type is open? if not, is there a better way to do it? Thanks.

like image 643
vexe Avatar asked Sep 12 '14 15:09

vexe


2 Answers

You could use IsGenericTypeDefinition:

typeof(Bar<,>).IsGenericTypeDefinition // true
typeof(Bar<int, string>).IsGenericTypeDefinition // false
like image 166
Andrew Whitaker Avatar answered Nov 11 '22 13:11

Andrew Whitaker


Type.IsGenericTypeDefinition is not technically the correct property to rule out open types. It will however work just fine in your case (and indeed in most other cases).

That being said, a type can be open without being a generic type definition. In the more general case, e.g. in a public method that accepts a Type parameter, what you really want is Type.ContainsGenericParameters.

For full details see the answer to this question:
Difference between Type.IsGenericTypeDefinition and Type.ContainsGenericParameters

TL;DR: The latter is recursive, while the former is not, and can thus be "fooled" by constructing a generic type that has a generic type definition as at least one of its generic type parameters.

like image 22
AnorZaken Avatar answered Nov 11 '22 13:11

AnorZaken