Determine if a generic type is open?
There are a bunch of regular, private and public types in my assembly. I have a query that I am trying to exclude public 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"
After debugging generic open type arguments, I found theirs to FullName
be null (as well as other things like DeclaringMethod
). So this can be one of the ways:
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 find out if a type is open? if not, is there a better way to do this? Thank.
source to share
You can use IsGenericTypeDefinition
:
typeof(Bar<,>).IsGenericTypeDefinition // true
typeof(Bar<int, string>).IsGenericTypeDefinition // false
source to share
Type.IsGenericTypeDefinition is not a technically correct property to exclude public types. However, in your case it will be very good (and even in most other cases).
However, a type can be open without defining a generic type. More generally, for example, in a public method that takes a type parameter, you really want Type.ContainsGenericParameters .
See the answer to this question for more details:
Difference between Type.IsGenericTypeDefinition and Type.ContainsGenericParameters
TL; DR: the latter is recursive and the former is not, and therefore can be "tricked" by constructing a generic type that has a generic type definition as at least one of its typical type parameters.
source to share