如何查找程序集中作为通用抽象类的实例并实现某个接口的所有类?
注意:
该接口也可以在一个继承自另一个实现接口的类的类中实现。
一个具体的例子:
我有bellow接口和Middleware-Class:
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
如何找到实现抽象类的HelloWorldHandler等所有类,并实现IHttpHandler。
请注意,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("/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();
}
}
答案 0 :(得分:2)
你的问题实际上非常复杂。
问题是你的类派生自泛型类,其泛型参数实现了IHttpHandler。
您需要获取继承(基础)类型(因为您从中继承)。
这是一种通用类型,因此您需要检查它是否是泛型类型。
如果是,则需要获取泛型类型(GetGenericTypeDefinition)
然后,您需要检查泛型类型是否为HandlerMiddleware&lt;&gt;类型
然后你需要从泛型类型中获取参数。
然后你需要检查第一个通用参数(如果它有一个)
然后,您需要检查泛型参数的类型(或它的派生基础)是否实现了相关接口。
所以在你的情况下:
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
这就是你如何得到这份清单。
答案 1 :(得分:-1)
这为您提供了在当前域的程序集中实现IHttpHandler的所有类:
internal Context context;
internal DbSet<Tariff> dbSet;
public TariffService() // the `TariffService` class is the place where I call
// `GetFilteredPublished`
{
context = new Context();
dbSet = context.Set<Tariff>();
}
要检查它是否来自通用抽象类,您可以使用以下命令:
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);
}
}
请参阅:Check if a class is derived from a generic class
用法:IsSubclassOfRawGeneric(typeof(HandlerMiddleware&lt;&gt;),typeToCheck)