I have a generic base class and I eventually would have many derived classes. I am trying to write a function which would return all these sub classes but everything I have tried so far has not worked.
public abstract class Index<T>
where T : class
{
public abstract string IndexName { get; }
public abstract string TypeName { get; }
public abstract Expression<Func<T, IConvertible>> IdFieldSelector { get; }
public string MakeSearchId(T item)
{
return ToSearchId(IdFieldSelector.Compile().Invoke(item));
}
public string MakeSearchId(IConvertible idValue)
{
return ToSearchId(idValue);
}
private static string ToSearchId(IConvertible idValue)
{
return idValue.ToString(CultureInfo.InvariantCulture);
}
}
sample subclass:
public class SurveyChangedIndex : Index<SurveyChanged>
{
public override string IndexName => "reviews";
public override string TypeName => "review";
public override Expression<Func<SurveyChanged, IConvertible>> IdFieldSelector => sc => sc.SurveyResponseId;
}
sample function:
var indexBase = typeof(Index<>);
var indexes = Assembly.GetAssembly(indexBase)
.GetTypes()
.Where(type =>
type != indexBase &&
!type.IsInterface &&
!type.IsAbstract &&
type.BaseType == indexBase)
.ToList();
You can do the following (C# 7 syntax follows):
public static IEnumerable<Type> GetAllDescendantsOf(
this Assembly assembly,
Type genericTypeDefinition)
{
IEnumerable<Type> GetAllAscendants(Type t)
{
var current = t;
while (current.BaseType != typeof(object))
{
yield return current.BaseType;
current = current.BaseType;
}
}
if (assembly == null)
throw new ArgumentNullException(nameof(assembly));
if (genericTypeDefinition == null)
throw new ArgumentNullException(nameof(genericTypeDefinition));
if (!genericTypeDefinition.IsGenericTypeDefinition)
throw new ArgumentException(
"Specified type is not a valid generic type definition.",
nameof(genericTypeDefinition));
return assembly.GetTypes()
.Where(t => GetAllAscendants(t).Any(d =>
d.IsGenericType &&
d.GetGenericTypeDefinition()
.Equals(genericTypeDefinition)));
}
This will return any type that inherits directly or indirectly from the specified generic type definition.
In the following scenario:
class Base { }
class Base<T>: Base { }
class Foo : Base<int> { }
class Bar : Base<string> { }
class Frob : Bar { }
class FooBar: Base { };
var genericTypeDefinition = typeof(Base<>);
var types = Assembly.GetExecutingAssembly()
.GetAllDescendantsOf(genericTypeDefinition)));
GetAllDescendantsOf
will output Foo
, Bar
and Frob
.