【问题标题】:Implementations of interface through Reflection通过反射实现接口
【发布时间】:2010-09-09 23:07:48
【问题描述】:

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

【问题讨论】:

标签: c# reflection interface


【解决方案1】:

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

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

这样使用;

var disposableTypes =  TypesImplementingInterface(typeof(IDisposable));

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

public static bool IsRealClass(Type testType)
{
    return testType.IsAbstract == false
         && testType.IsGenericTypeDefinition == false
         && testType.IsInterface == false;
}

【讨论】:

  • 请注意,这段代码看不到未来——它无法在尚未加载的接口中找到该接口的实现。
  • 我想我可以把它变成Type的扩展方法,结果可能会很有用。
  • 史蒂夫:你能解释一下我遇到的类似问题吗:stackoverflow.com/questions/5849210/…
  • 您可以将IsRealClass 简化为return !(testType.IsAbstract || testType.IsGenericTypeDefinition || testType.IsInterface);
  • .SelectMany(assembly => assembly.GetTypes()) 这行给了我以下异常: {"Could not load file or assembly 'Microsoft.WindowsAzure.MobileServices.Management, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f300afd708cefcd3' 或其依赖项之一。系统找不到指定的文件。":"Microsoft.WindowsAzure.MobileServices.Management, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f300afd708cefcd3"}跨度>
【解决方案2】:

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

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

这是一个例子。 myInterface 是您正在搜索的接口和实现。

Assembly myAssembly;
Type myInterface;
foreach (Type type in myAssembly.GetTypes())
{
    if (myInterface.IsAssignableFrom(type))
        Console.WriteLine(type.FullName);
}

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

【讨论】:

    【解决方案3】:
    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;
           }
      }
    }
    

    也许是这样的......

    【讨论】:

    • 这在实现上述接口的other程序集中找不到类型。
    【解决方案4】:

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

    代码

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

    示例

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

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

    获取当前AppDomain中的实现者:

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

    【讨论】:

      【解决方案5】:

      你是指一个类型实现的所有接口吗?

      像这样:

      ObjX foo = new ObjX();
      Type tFoo = foo.GetType();
      Type[] tFooInterfaces = tFoo.GetInterfaces();
      foreach(Type tInterface in tFooInterfaces)
      {
        // do something with it
      }
      

      希望对您有所帮助。

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          猜你喜欢
          • 2017-01-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-21
          • 1970-01-01
          • 2023-03-03
          • 2018-01-25
          • 1970-01-01
          相关资源
          最近更新 更多