public record GenericArgumentResult(Type RequestedType, Type DirectSubclass, Type[] GenericArguments);
public static class GenericTypeHelper
{
///
/// Returns of ,
/// even from : .
///
/// For e.g EntityTypeBuilderOfEntity.
/// for e.g typeof().
/// An enumerable of generic arguments of .
public static IEnumerable GetGenericArgumentsOfTypeDefinition(
Type concreteType,
Type genericDefinition
)
{
return EnumerateBaseTypesAndInterfaces(concreteType)
.Where(x => x.IsGenericType)
.Where(x => x.GetGenericTypeDefinition() == genericDefinition)
.Select(x => new GenericArgumentResult(
RequestedType: concreteType,
DirectSubclass: x,
GenericArguments: x.GenericTypeArguments
));
}
// same as GetGenericArgumentsOfTypeDefinition but returns only the first result
public static GenericArgumentResult? GetFirstGenericArgumentsOfTypeDefinition(
Type concreteType,
Type genericDefinition,
Func? predicate = null
)
{
var result = GetGenericArgumentsOfTypeDefinition(concreteType, genericDefinition);
if (predicate != null)
{
result = result.Where(predicate);
}
return result.FirstOrDefault();
}
private static IEnumerable EnumerateBaseTypesAndInterfaces(Type? type, bool returnInput = true)
{
if (type == null)
{
yield break;
}
if (returnInput)
{
yield return type;
}
// Return all base types
var current = type.BaseType;
while (current != null)
{
foreach (var interfaceType in current.GetInterfaces())
{
yield return interfaceType;
}
yield return current;
current = current.BaseType;
}
// Return all interfaces
foreach (var interfaceType in type.GetInterfaces())
{
yield return interfaceType;
}
}
}