【问题标题】:How do I get all instances of all loaded types that implement a given interface?如何获取实现给定接口的所有加载类型的所有实例?
【发布时间】:2008-11-19 16:43:31
【问题描述】:

我们需要获取实现给定接口的所有对象实例 - 我们可以这样做吗?如果可以,如何做?

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    如果您需要实现特定接口的所有类型的实例(示例),您可以遍历所有类型,检查接口并在找到匹配项时创建实例。

    这里有一些伪代码,看起来非常像 C#,甚至可以编译并返回你需要的东西。如果不出意外,它将为您指明正确的方向:

    public static IEnumerable<T> GetInstancesOfImplementingTypes<T>()
    {
        AppDomain app = AppDomain.CurrentDomain;
        Assembly[] ass = app.GetAssemblies();
        Type[] types;
        Type targetType = typeof(T);
    
        foreach (Assembly a in ass)
        {
            types = a.GetTypes();
            foreach (Type t in types)
            {
                if (t.IsInterface) continue;
                if (t.IsAbstract) continue;
                foreach (Type iface in t.GetInterfaces())
                {
                    if (!iface.Equals(targetType)) continue;
                    yield return (T) Activator.CreateInstance(t);
                    break;
                }
            }
        }
    }
    

    现在,如果您正在谈论遍历堆并返回实现特定类型的所有对象的先前实例化实例,那么祝您好运,因为 .Net 运行时不存储此信息(可由调试器/分析器计算通过检查堆/堆栈)。

    根据您认为需要这样做的原因,可能有更好的方法。

    【讨论】:

    • 是的,我想获得以前实例化的实例。这是因为我们使用实现相同接口的对象加载存储其设置的模块,但似乎没有任何其他方法可以获取设置实例。
    • +1 谢谢。向 T 添加了强制转换,使代码为我编译。
    • 对于不能导出到调用程序集的类型,这将失败,但如果你看的话,有一个解决方法......
    • 这是枚举引用程序集中定义的所有类型,而不是这些类型的所有实例。
    • @CharlesBretana 好吧,感谢您对这个已有近 9 年历史的答案的提醒!我会引导你到original question as it was posted and answered。您会注意到 OP 不清楚他在问什么。我试了一下,至少有几个人同意我的看法。请注意,那是在 SO 没有 cmets 也没有能力通过特定关闭原因提供反馈的那一天。我还想请你去别处学究气。感谢您的参与!
    【解决方案2】:

    我不相信有办法...您必须能够遍历堆并检查那里的每个对象,或者遍历应用程序进程空间中每个活动线程的堆栈,检查每个堆栈每个线程上的引用变量...

    另一种方式,(我猜你做不到)是拦截所有对象创建活动(使用容器方法)并保留应用程序中所有对象的列表......

    【讨论】:

    【解决方案3】:

    一个对象的所有实例,还是所有类型?

    获取对象的所有实例几乎是不可能的,并且会涉及有关通过管理内存进行扫描的非公开信息。

    获取实现给定接口的所有类型是可行的 --- 在给定域内。 (即,您可以找到在实现特定接口的程序集中定义的所有类型)

    • 加载程序集
    • 遍历它的类型(调用 asm.GetTypes())
    • 检查 typeof(IMyInterface).IsAssignibleFrom(testType)

    【讨论】:

      【解决方案4】:

      如果实现指定接口的类是你的,那么你可以在实例化时实现一个弱引用列表。

      【讨论】:

      • 恐怕它们不全是我们的。
      【解决方案5】:
      IEnumerable<Type> GetAllTypesThatImplementInterface<T>()
      {
          var @interface = typeof (T);
          return @interface.IsInterface
                     ? AppDomain.CurrentDomain.GetAssemblies()
                           .SelectMany(assembly => assembly.GetTypes())
                           .Where(type => !type.IsInterface
                                       && !type.IsAbstract 
                                       && type.GetInterfaces().Contains(@interface))
                     : new Type[] {};
      }
      

      【讨论】:

      • 不错 - 但我如何获得这些类型的实例?
      • @Simon,唯一的方法是在创建时注册对每个实例的引用。如果不预先建立这样的机制,您将无法访问它们。根据您的用例,您可能需要查看ObservableCollection...您的用例是什么?
      • 这是根据我在@Will 的回答中的评论 - 我们使用实现相同接口的对象加载存储其设置的模块,但似乎没有任何其他方法可以获取设置实例.
      • @Simon,你能重构模块以在加载时注册设置实例吗?
      • 恐怕不行——我们可以在我们可以访问的地方做到这一点,但还有一些我们没有。
      猜你喜欢
      • 1970-01-01
      • 2010-09-06
      • 1970-01-01
      • 2015-11-22
      • 1970-01-01
      • 1970-01-01
      • 2011-10-24
      相关资源
      最近更新 更多