关于c#:通过反射实现接口

关于c#:通过反射实现接口

Implementations of interface through Reflection

如何通过C#中的反射获取接口的所有实现?


答案是这样;它会搜索整个应用程序域-即您的应用程序当前加载的每个程序集。

1
2
3
4
5
6
7
8
9
10
11
/// <summary>
/// Returns all types in the current AppDomain implementing the interface or inheriting the type.
/// </summary>
public static IEnumerable<Type> TypesImplementingInterface(Type desiredType)
{
    return AppDomain
           .CurrentDomain
           .GetAssemblies()
           .SelectMany(assembly => assembly.GetTypes())
           .Where(type => desiredType.IsAssignableFrom(type));
}

它是这样使用的;

1
var disposableTypes =  TypesImplementingInterface(typeof(IDisposable));

您可能还希望此函数查找实际的具体类型-即过滤掉抽象,接口和通用类型定义。

1
2
3
4
5
6
public static bool IsRealClass(Type testType)
{
    return testType.IsAbstract == false
         && testType.IsGenericTypeDefinition == false
         && testType.IsInterface == false;
}

看看Assembly.GetTypes()方法。它返回可在程序集中找到的所有类型。您要做的就是遍历每个返回的类型,并检查其是否实现了必要的接口。

这样做的一种方法是使用Type.IsAssignableFrom方法。

这是例子。 myInterface是您要搜索的接口。

1
2
3
4
5
6
7
Assembly myAssembly;
Type myInterface;
foreach (Type type in myAssembly.GetTypes())
{
    if (myInterface.IsAssignableFrom(type))
        Console.WriteLine(type.FullName);
}

我确实认为这不是解决问题的有效方法,但是至少,这是一个很好的起点。


1
2
3
4
5
6
7
8
9
10
11
Assembly assembly = Assembly.GetExecutingAssembly();
List<Type> types = assembly.GetTypes();
List<Type> childTypes = new List<Type>();
foreach (Type type in Types) {
  foreach (Type interfaceType in type.GetInterfaces()) {
       if (interfaceType.Equals(typeof([yourinterfacetype)) {
            childTypes.Add(type)
            break;
       }
  }
}

也许像那样...


正如Simon Farrow所建议的,这是一些可能有用的Type扩展方法。这段代码只是对已接受答案的重组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/// <summary>
/// Returns all types in <paramref name="assembliesToSearch"/> that directly or indirectly implement or inherit from the given type.
/// </summary>
public static IEnumerable<Type> GetImplementors(this Type abstractType, params Assembly[] assembliesToSearch)
{
    var typesInAssemblies = assembliesToSearch.SelectMany(assembly => assembly.GetTypes());
    return typesInAssemblies.Where(abstractType.IsAssignableFrom);
}

/// <summary>
/// Returns the results of <see cref="GetImplementors"/> that match <see cref="IsInstantiable"/>.
/// </summary>
public static IEnumerable<Type> GetInstantiableImplementors(this Type abstractType, params Assembly[] assembliesToSearch)
{
    var implementors = abstractType.GetImplementors(assembliesToSearch);
    return implementors.Where(IsInstantiable);
}

/// <summary>
/// Determines whether <paramref name="type"/> is a concrete, non-open-generic type.
/// </summary>
public static bool IsInstantiable(this Type type)
{
    return !(type.IsAbstract || type.IsGenericTypeDefinition || type.IsInterface);
}

例子

要在调用程序集中获取可实例化的实现器:

1
2
var callingAssembly = Assembly.GetCallingAssembly();
var httpModules = typeof(IHttpModule).GetInstantiableImplementors(callingAssembly);

要在当前AppDomain中获取实现者:

1
2
var appDomainAssemblies = AppDomain.CurrentDomain.GetAssemblies();
var httpModules = typeof(IHttpModule).GetImplementors(appDomainAssemblies);

您必须遍历所有感兴趣的程序集。从程序集中,您可以获得其定义的所有类型。请注意,当您执行AppDomain.CurrentDomain.Assemblies时,只会得到已加载的程序集。直到需要时才加载装配件,这意味着您必须在开始搜索之前显式加载装配件。


您是说Type实现的所有接口吗?

像这样:

1
2
3
4
5
6
7
ObjX foo = new ObjX();
Type tFoo = foo.GetType();
Type[] tFooInterfaces = tFoo.GetInterfaces();
foreach(Type tInterface in tFooInterfaces)
{
  // do something with it
}

希望有帮助。


推荐阅读