Reflect all possible permutations of a generic typ

2019-04-11 19:11发布

问题:

Given a generic type with constraints:

class MyClass<T> where T: Alpha
{
}

and implementations of that constraint:

class Alpha {}
class Bravo : Alpha {}
class Charlie : Alpha {}

How can get generic types for all the combinations at run-time?

// I want these types at run-time
MyClass<Alpha> 
MyClass<Bravo> 
MyClass<Charlie> 

EDIT: Based on @rich.okelly's answer, I think the real question is this:

How can I find all the types that implement my generic type's constraint at run-time?

So if I'm given typeof(MyClass<>), I get the types above.

回答1:

Something like:

var alphaType = typeof(Alpha);
var allTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(t => alphaType.IsAssignableFrom(t));
var myClass = typeof(MyClass<>);
foreach (var type in allTypes) 
{
  var genericType = myClass.MakeGenericType(type);
}

Alternatively, if the generic types have already been loaded:

var allTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(MyClass<>));
foreach (var type in allTypes) 
{
  ...
}

Update

You can use the GetGenericArguments() method and the GetGenericParameterConstraints() method to get the required types.

var myType = typeof(MyClass<>);
var typeConstraints = myType.GetGenericArguments().First().GetGenericParameterConstraints();
var allTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes());
var genericTypes = allTypes.Where(t => typeConstraints.All(tc => tc.IsAssignableFrom(t))).Select(t => myType.MakeGenericType(t));
foreach (var type in genericTypes)
{
    ...
}


回答2:

You can enumerate all loaded assemblies in the app domain. And then enumerate all the types in each Assembly and test to see if each type is a subclass of the constant.