Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何查找程序集中属于泛型抽象类实例的所有类并实现特定接口_C#_Asp.net_.net_Asp.net Core_.net Core - Fatal编程技术网

C# 如何查找程序集中属于泛型抽象类实例的所有类并实现特定接口

C# 如何查找程序集中属于泛型抽象类实例的所有类并实现特定接口,c#,asp.net,.net,asp.net-core,.net-core,C#,Asp.net,.net,Asp.net Core,.net Core,如何在程序集中找到作为泛型抽象类实例的所有类并实现某个接口 注: 该接口也可以在从实现该接口的另一个类继承的类中实现 一个具体的例子: 我有下面的接口和中间件类: public interface IHttpHandler { bool IsReusable { get; } void ProcessRequest(HttpContext context); } public abstract class HandlerMiddleware<T> where T:

如何在程序集中找到作为泛型抽象类实例的所有类并实现某个接口

注:
该接口也可以在从实现该接口的另一个类继承的类中实现

一个具体的例子:
我有下面的接口和中间件类:

public interface IHttpHandler
{
    bool IsReusable { get; }
    void ProcessRequest(HttpContext context);
}

public abstract class HandlerMiddleware<T> where T: IHttpHandler
{

    private readonly RequestDelegate _next;

    public HandlerMiddleware()
    { }

    public HandlerMiddleware(RequestDelegate next)
    {
        _next = next;
    }


    public async Task Invoke(HttpContext context)
    {    
        await SyncInvoke(context);
    }


    public Task SyncInvoke(HttpContext context)
    {
        // IHttpHandler handler = (IHttpHandler)this;
        T handler = System.Activator.CreateInstance<T>();

        handler.ProcessRequest(context);
        return Task.CompletedTask;
    }


} // End Abstract Class HandlerMiddleware
公共接口IHttpHandler
{
布尔可重用{get;}
void ProcessRequest(HttpContext上下文);
}
公共抽象类handler中间件,其中T:IHttpHandler
{
private readonly RequestDelegate\u next;
公共HandlerMiddleware()
{ }
公共HandlerMiddleware(RequestDelegate下一步)
{
_下一个=下一个;
}
公共异步任务调用(HttpContext上下文)
{    
等待同步调用(上下文);
}
公共任务SyncInvoke(HttpContext上下文)
{
//IHttpHandler handler=(IHttpHandler)this;
T handler=System.Activator.CreateInstance();
ProcessRequest(上下文);
返回Task.CompletedTask;
}
}//结束抽象类handler中间件
如何找到所有实现抽象类和IHttpHandler的类,如HelloWorldHandler

请注意,HandlerMiddleware是通用的
它应该找到所有处理程序,例如HelloWorldHandler1和HelloWorldHandler2

[HandlerPath("/hello")]
public class HelloWorldHandler 
    : HandlerMiddleware<HelloWorldHandler>, IHttpHandler
{
    public HelloWorldHandler() :base() { }
    public HelloWorldHandler(RequestDelegate next):base(next) { }

    void IHttpHandler.ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";

        //await context.Response.WriteAsync("Hello World!");
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes("hello world");
        context.Response.Body.Write(buffer, 0, buffer.Length);
    }

    bool IHttpHandler.IsReusable
    {
        get
        {
            return false;
        }
    }

}
[HandlerPath(“/hello”)]
公共类HelloWorldHandler
:handler,IHttpHandler
{
公共HelloWorldHandler():base(){}
公共HelloWorldHandler(RequestDelegate下一个):基(下一个){}
void IHttpHandler.ProcessRequest(HttpContext上下文)
{
context.Response.ContentType=“text/plain”;
//wait context.Response.WriteAsync(“Hello World!”);
byte[]buffer=System.Text.Encoding.UTF8.GetBytes(“hello world”);
context.Response.Body.Write(buffer,0,buffer.Length);
}
布尔·伊赫特芬德勒是可维修的
{
得到
{
返回false;
}
}
}
如果该方法也找到此构造,则可获得额外点数:

[HandlerPath("/hello2")]
public class HelloWorldHandler2
: HandlerMiddleware<Middleman>
{

    public HelloWorldHandler2() :base() { }
    public HelloWorldHandler2(RequestDelegate next):base(next) { }

}


public class Middleman
    : IHttpHandler
{
    bool IHttpHandler.IsReusable => throw new NotImplementedException();

    void IHttpHandler.ProcessRequest(HttpContext context)
    {
        throw new NotImplementedException();
    }
}
[HandlerPath(“/hello2”)]
公共类HelloWorldHandler2
:handler中间件
{
公共HelloWorldHandler2():base(){}
公共HelloWorldHandler2(RequestDelegate下一个):基(下一个){}
}
公营中间人
:IHttpHandler
{
bool IHttpHandler.IsReusable=>抛出新的NotImplementedException();
void IHttpHandler.ProcessRequest(HttpContext上下文)
{
抛出新的NotImplementedException();
}
}

这将为您提供在当前域的程序集中实现IHttpHandler的所有类:

 List<Type> result = new List<Type>();

        var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();

        foreach(var assem in assemblies)
        {
            var list = assem.GetExportedTypes().Where(t => t.GetInterfaces().Contains(typeof(IHttpHandler))).ToList();

            if (list != null && list.Count != 0)
            {
                result.AddRange(list);
            }
        }
见:


用法:IsSubclassOfRawGeneric(typeof(HandlerMiddleware),typeToCheck)

您的问题实际上相当复杂,难以理解
问题是您的类是从泛型类派生的,其泛型参数实现了IHttpHandler

您需要获取继承的(基)类型(因为您是从它继承的)
这是泛型类型,所以需要检查它是否是泛型类型
如果是es,则需要获取泛型类型(GetGenericTypeDefinition)。
然后需要检查泛型类型是否为HandlerMiddleware类型
然后需要从泛型类型中获取参数
然后需要检查第一个泛型参数(如果有)。
然后,您需要检查泛型参数的类型(或其派生基)是否实现了所讨论的接口

因此,在你的情况下:

var ls = FindDerivedTypes(t.Assembly, typeof(HandlerMiddleware<>), typeof(IHttpHandler));
        System.Console.WriteLine(ls);



public static List<System.Type> FindDerivedTypes(Assembly assembly
    , System.Type typeToSearch
    ,System.Type neededInterface)
{
    List<System.Type> ls = new List<System.Type>();

    System.Type[] ta = assembly.GetTypes();

    int l = ta.Length;
    for (int i = 0; i < l; ++i)
    {
        if (ta[i].BaseType == null)
            continue;

        if (!ta[i].BaseType.IsGenericType)
            continue;

        // public class Middleman : IHttpHandler
        // public class HelloWorldHandler2 : HandlerMiddleware<Middleman>
        // public class HelloWorldHandler : HandlerMiddleware<HelloWorldHandler>, IHttpHandler

        var gt = ta[i].BaseType.GetGenericTypeDefinition();
        if (gt == null)
            continue;

        if (!object.ReferenceEquals(gt, typeToSearch))
            continue;

        Type[] typeParameters = ta[i].BaseType.GetGenericArguments();
        if (typeParameters == null || typeParameters.Length < 1)
            continue;

        if(neededInterface.IsAssignableFrom(typeParameters[0]))
            ls.Add(ta[i]);
    } // Next i 

    return ls;
} // End Function FindDerivedTypes
var ls=FindDerivedTypes(t.Assembly,typeof(handler中间件),typeof(IHttpHandler));
系统控制台写入线(ls);
公共静态列表查找驱动类型(程序集
,System.Type typeToSearch
,System.Type需要接口)
{
列表ls=新列表();
System.Type[]ta=assembly.GetTypes();
int l=ta.长度;
对于(int i=0;i

这就是你得到这份名单的原因

实现了IHttpHandler的所有结构类HandlerMiddleware(不管实现本身是否抛出未实现)。这个“查找”的上下文是什么?您是在寻找有关如何使用Visual Studio的建议,还是希望编写在运行时执行此搜索的反射代码?@Damien_The_unsiever:问得好。我的意思是在运行时搜索。只需使用
typeof(HandlerMiddleware).IsAssignableFrom(type)和&typeof(IHttpHandler).IsAssignableFrom(type)
。扩展到
typeof(在汇编中键入).assembly.GetTypes().Where(t=>typeof(HandlerMiddleware).IsAssignableFrom(t)和&typeof(IHttpHandler.IsAssignableFrom(type)).ToArray()可能重复的否,您不能,因为IsSubclassOf类型是泛型类型。确定,为泛型类型添加了另一段代码
var ls = FindDerivedTypes(t.Assembly, typeof(HandlerMiddleware<>), typeof(IHttpHandler));
        System.Console.WriteLine(ls);



public static List<System.Type> FindDerivedTypes(Assembly assembly
    , System.Type typeToSearch
    ,System.Type neededInterface)
{
    List<System.Type> ls = new List<System.Type>();

    System.Type[] ta = assembly.GetTypes();

    int l = ta.Length;
    for (int i = 0; i < l; ++i)
    {
        if (ta[i].BaseType == null)
            continue;

        if (!ta[i].BaseType.IsGenericType)
            continue;

        // public class Middleman : IHttpHandler
        // public class HelloWorldHandler2 : HandlerMiddleware<Middleman>
        // public class HelloWorldHandler : HandlerMiddleware<HelloWorldHandler>, IHttpHandler

        var gt = ta[i].BaseType.GetGenericTypeDefinition();
        if (gt == null)
            continue;

        if (!object.ReferenceEquals(gt, typeToSearch))
            continue;

        Type[] typeParameters = ta[i].BaseType.GetGenericArguments();
        if (typeParameters == null || typeParameters.Length < 1)
            continue;

        if(neededInterface.IsAssignableFrom(typeParameters[0]))
            ls.Add(ta[i]);
    } // Next i 

    return ls;
} // End Function FindDerivedTypes