获取通用抽象基类

时间:2018-01-15 15:41:49

标签: c# .net-core system.reflection

我有一个通用的基类,我最终会有很多派生类。 我正在尝试编写一个函数来返回所有这些子类,但到目前为止我尝试的所有东西都没有用。

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);
    }
}

示例子类:

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();

2 个答案:

答案 0 :(得分:1)

您可以执行以下操作(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)));
}

这将返回从指定的泛型类型定义直接或间接继承的任何类型。

在以下情形中:

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将输出FooBarFrob

答案 1 :(得分:0)

这应解决您的代码:

var indexes = Assembly.GetAssembly(indexBase)
     .GetTypes()
     .Where(type =>
         type != indexBase &&
         !type.IsInterface &&
         !type.IsAbstract &&
         type.BaseType.IsAssignableFrom(indexBase))
     .ToList();