获取通用抽象基 class 的所有子 classes
Get all sub classes of generic abstract base class
我有一个通用的基础 class,我最终会有很多派生的 classes。
我正在尝试编写一个函数,它将 return 所有这些子 classes 但到目前为止我尝试的一切都没有奏效。
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);
}
}
子样本class:
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;
}
示例函数:
var indexBase = typeof(Index<>);
var indexes = Assembly.GetAssembly(indexBase)
.GetTypes()
.Where(type =>
type != indexBase &&
!type.IsInterface &&
!type.IsAbstract &&
type.BaseType == indexBase)
.ToList();
这应该可以解决您的代码问题:
var indexes = Assembly.GetAssembly(indexBase)
.GetTypes()
.Where(type =>
type != indexBase &&
!type.IsInterface &&
!type.IsAbstract &&
type.BaseType.IsAssignableFrom(indexBase))
.ToList();
您可以执行以下操作(C# 7 语法如下):
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)));
}
这将 return 直接或间接继承自指定泛型类型定义的任何类型。
在以下情况下:
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
将输出 Foo
、Bar
和 Frob
.
这对我有用:
var indexes = Assembly.GetAssembly(indexBase)
.GetTypes()
.Where(IsIndexType)
.ToArray();
和
private bool IsIndexType(Type type)
{
var indexDefinition = typeof(Index<>).GetGenericTypeDefinition();
return !type.IsAbstract
&& type.IsClass
&& type.BaseType is not null
&& type.BaseType.IsGenericType
&& type.BaseType.GetGenericTypeDefinition() == indexDefinition;
}
我有一个通用的基础 class,我最终会有很多派生的 classes。 我正在尝试编写一个函数,它将 return 所有这些子 classes 但到目前为止我尝试的一切都没有奏效。
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);
}
}
子样本class:
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;
}
示例函数:
var indexBase = typeof(Index<>);
var indexes = Assembly.GetAssembly(indexBase)
.GetTypes()
.Where(type =>
type != indexBase &&
!type.IsInterface &&
!type.IsAbstract &&
type.BaseType == indexBase)
.ToList();
这应该可以解决您的代码问题:
var indexes = Assembly.GetAssembly(indexBase)
.GetTypes()
.Where(type =>
type != indexBase &&
!type.IsInterface &&
!type.IsAbstract &&
type.BaseType.IsAssignableFrom(indexBase))
.ToList();
您可以执行以下操作(C# 7 语法如下):
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)));
}
这将 return 直接或间接继承自指定泛型类型定义的任何类型。
在以下情况下:
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
将输出 Foo
、Bar
和 Frob
.
这对我有用:
var indexes = Assembly.GetAssembly(indexBase)
.GetTypes()
.Where(IsIndexType)
.ToArray();
和
private bool IsIndexType(Type type)
{
var indexDefinition = typeof(Index<>).GetGenericTypeDefinition();
return !type.IsAbstract
&& type.IsClass
&& type.BaseType is not null
&& type.BaseType.IsGenericType
&& type.BaseType.GetGenericTypeDefinition() == indexDefinition;
}