提问者:小点点

获取一个泛型抽象类的所有继承类


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

在实现抽象方法以获得我想要的类实现时,我一直遵循此Change参数类型,类似于以下内容:

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

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继承的所有类A和B

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

谢谢!


共3个答案

匿名用户

实际上可以通过分解抽象类来让实例调用Search()(并且只有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上的类型约束。

匿名用户

像这样的东西应该可以做到:

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;

匿名用户

这对我在几个独立的项目中起作用

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