【问题标题】:Get all inherited classes of a generic abstract class获取一个泛型抽象类的所有继承类
【发布时间】:2014-12-03 09:40:08
【问题描述】:

我正在寻找某种方法来获取所有继承通用抽象类的类,并对每个类执行一个方法。

我一直在关注这个Change parameter type when implementing an abstract method 以获得我想要的类实现,类似于这样:

public abstract class AbstractRequest<TResponseData>
                where TResponseData : IResponseData
{
    public abstract void Search();
    public abstract GoodData BindData(TResponseData data);
}

public interface IResponseData
{
}

public class AResponse : IResponseData
{
}

public class BResponse : IResponseData
{
}

public class A : AbstractRequest<AResponse>
{
    public override void Search()
    {
        // get AResponse
        // Call to BindData() with AResponse
    }
    public override GoodData BindData(AResponse data)
    {
        // Bind the data from AResponse to GoodData
    }
}

public class B : AbstractRequest<BResponse>
{
    public override void Search()
    {
        // Get BResponse
        // Call to BindData() with BResponse
    }
    public override GoodData BindData(BResponse data)
    {
        // Bind the data from BResponse to GoodData
    }
}    

这是有效的查找,直到我需要获取所有 A 和 B 类并为每个类调用 Search() 方法。对于非泛型抽象类,我可以使用以下 sn-p 来获取类

var instances = from t in Assembly.GetExecutingAssembly().GetTypes()
                where t.IsSubclassOf(typeof(AbstractRequest))
                    && t.GetConstructor(Type.EmptyTypes) != null
                select Activator.CreateInstance(t) as AbstractRequest;

那么,我怎样才能得到继承自AbstractRequest&lt;AResponse&gt;AbstractRequest&lt;BResponse&gt;的所有类A和B呢?

编辑:我忘了提。假设会有许多类似于 A 或 B 的实现,并且会随着时间的推移而添加。我想要一个“优雅”(如果可能的话)的解决方案,所以稍后我只需要处理 C、D 等的实现。

谢谢!

【问题讨论】:

    标签: c# inheritance abstract


    【解决方案1】:

    这在几个单独的项目中对我有用

    /// <summary>
    /// Find all subclasses of a given type via reflection
    /// </summary>
    /// <typeparam name="T">Parent class type</typeparam>
    /// <returns></returns>
    public Type[] GetAllSubclasses<T>() where T : class
    {
        Type[] types = Assembly.GetExecutingAssembly().GetTypes()
                               .Where(t => t.IsSubclassOf(typeof (T))).ToArray();
    
        return types;
    }
    

    要实例化然后执行一个方法,你可以试试这个模式:

    // Create new instances, then use those to execute some method.
    foreach (Type T in GetAllSubclasses<MyType>())
    {
        MyType mt = (MyType) Activator.CreateInstance(T);
        mt.MyMethod(someArgs);
    }
    

    【讨论】:

    • 感谢您的回答!我认为您的解决方案与我所做的几乎相同。问题是MyType 是一个泛型类型(在我的例子中是AbstractRequest&lt;IResponseData&gt;,而A 类和B 类将继承自更具体的类AbstractRequest&lt;AResponse&gt;AbstractRequest&lt;BResponse&gt;
    【解决方案2】:

    实际上可以通过分解抽象类来让实例调用 Search()(并且只有搜索):

    public abstract class AbstractRequest
    {
        public abstract void Search();
    }
    
    public abstract class AbstractRequest<TResponseData> : AbstractRequest
                where TResponseData : IResponseData
    {
        public abstract GoodData BindData(TResponseData data);
    }
    

    然后您可以使用您的原始(非通用)代码:

    var instances = from t in Assembly.GetExecutingAssembly().GetTypes()
        where t.IsClass &&
              typeof(AbstractRequest).IsAssignableFrom(t) &&
              t.GetConstructor(Type.EmptyTypes) != null
        select Activator.CreateInstance(t) as AbstractRequest;
    

    (旧的、失败的解决方案)

    我想我会做这样的事情(未经测试):

    var abstractRequestTypes =
        (from t in Assembly.GetExecutingAssembly().GetTypes()
         where t.IsClass &&
              typeof(IResponseData).IsAssignableFrom(t)
         select typeof(AbstractRequest<>).MakeGenericType(t)).ToList();
    
    var instanceTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
        where t.IsClass &&
              abstractRequestTypes.Any(dt => dt.IsAssignableFrom(t));
    

    这应该涵盖继承层次结构中的所有内容,利用AbstractRequest 上的类型约束。

    【讨论】:

    • 伙计,您编辑的答案正是我所需要的!!!经过测试,在我的情况下工作得很好。非常感谢!
    【解决方案3】:

    这样的事情应该可以解决问题:

    from t in Assembly.GetExecutingAssembly().GetTypes()
    where t.IsClass && 
          (typeof(AbstractRequest<AResponse>).IsAssignableFrom(t) ||
           typeof(AbstractRequest<BResponse>).IsAssignableFrom(t))
    select t;
    

    或者,如果您想获取从泛型类AbstractRequest 继承的所有类,您可以使用:

    from t in Assembly.GetExecutingAssembly().GetTypes()
    where t.IsClass && 
          t.BaseType != null &&
          t.BaseType.GetGenericTypeDefinition() == typeof(AbstractRequest<>)
    select t;
    

    【讨论】:

    • 感谢您的回答!我忘了提到它只是类似于 A 或 B 的众多实现中的 2 个,并且会随着时间的推移而添加。这肯定会奏效,但我想有一个更优雅的解决方案,所以稍后我只需要处理实现 C、D 等。
    • 它确实允许 typeof(AbstractRequest) ,您所说的仅在实例化类型时才成立。
    • @VikasGupta VS 2013 没有将其报告为编译错误,所以我认为这是可能的。 @Selman22 如果我的下一个问题很愚蠢,我很抱歉,但我是 C# 新手。那么如何构造t的实例并调用Search()方法呢?我尝试了var i = t.GetConstructor(Type.EmptyTypes).Invoke(null);,但 VS 在我调用i.Search() 时报告错误。
    猜你喜欢
    • 2011-07-21
    • 2023-04-03
    • 2021-07-05
    • 2020-01-30
    • 2017-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-10
    相关资源
    最近更新 更多