【问题标题】:List all DLL's implementing a specific interface from the GAC列出所有实现 GAC 特定接口的 DLL
【发布时间】:2009-04-14 14:53:19
【问题描述】:

阿罗哈

鉴于具有存储在 GAC 中的插件的插件架构 (C# / .NET 3.5),我如何列出/加载所有包含实现我的特定接口的类型的 dll?换句话说,我想通过查看 GAC 来调查我的应用程序的哪些插件安装在机器上。

-Edoode

【问题讨论】:

  • 小修正:DLL(程序集)不实现接口——但它们可能包含实现接口的类。
  • 请原谅我的无知,但是插件 dll 是否属于 gac?不在应用的应用程序文件夹中?
  • 一般来说,没有。插件应该与它们正在加载的应用程序一起使用。但是,如果这些是多应用插件,那么我可以理解为什么希望将它们放入 GAC。如果你这样做了,我会有配置来加载它们,而不仅仅是从 GAC 加载所有的。

标签: c# plugins gac


【解决方案1】:

要补充 BFree 的答案,我建议您可以load the assemblies for reflection only。这在没有应用程序域的情况下为您提供了增强的安全性(程序集根本无法执行)和灵活性(您可以加载用于不同体系结构的程序集)。

【讨论】:

    【解决方案2】:

    首先澄清一点:DLL 不能实现接口。 DLL 包含可以实现特定接口的类型。这是一个围绕 fusion.dll 的.NET wrapper,它允许您枚举 GAC 中的所有程序集。使用 Assembly.Load 加载程序集后,您可以尝试查找实现特定接口的所有类型:

    foreach (var type in assembly.GetTypes())
    {
        var myInterfaceType = typeof(IMyInterface);
        if (type != myInterfaceType && myInterfaceType.IsAssignableFrom(type))
        {
            Console.WriteLine("{0} implements IMyInterface", type);
        }
    }
    

    【讨论】:

    • 谢谢,gacapi (fusion.dll) 正是我所需要的 :) 剩下的就是我了。
    【解决方案3】:

    Gac 实际上只是您机器上的一个目录,就像其他任何目录一样。这是典型的细分:

    c:\windows\assembly\GAC
    
                       \GAC_32
    
                       \GAC_MSIL
    

    也许还有其他人..

    在每个文件夹中,您都会找到存储实际 dll 的子文件夹。您首先需要编写一个递归方法来获取在 \assembly\ 下找到的所有 dll,(如果您自己不习惯这样做,您可以轻松地在网上找到这些)。获得 dll 列表后,您可以继续使用 Assembly.LoadFile 加载程序集并检查所有类型以查看它们是否实现给定接口。

    我唯一的建议是将这些 dll 加载到单独的应用程序域中,这样您就不会允许任何潜在的有害 dll 加载到您的应用中。

    一些链接:

    Searching Directories.

    Loading Assemblies and checking for a given interface.

    Creating new AppDomain.

    【讨论】:

    • 我不能夸大使用另一个 AppDomain 的重要性。事实上,非常积极地回收 AppDomain 可能是一个更好的选择,因为您的内存消耗会随着您加载的每个程序集而增加。
    【解决方案4】:

    您应该查看 Enterprise Library 中的 Type Selector Tool。它可能不是您直接想要的,但它会执行您所描述的操作,并且您可以从中借用一些实现。

    【讨论】:

      【解决方案5】:

      首先,我建议不要这样做。为此,您必须从 GAC 加载所有程序集。我建议您让您的用户(或管理员或其他)告诉您尝试从哪些程序集加载(尽管为此,您可能需要所有选项的列表,这可能就是您问这个的原因。 ..)

      也就是说,这可能有效,但它会为它应该适用的几个程序集抛出错误,我不知道为什么....另外,我不知道如何检测 GAC 的位置 -- c :\windows\assembly 是默认值,但我不知道真正的值存储在哪里(注册表?)

      var targetType = typeof(IComparable);
      var errors = new List<Exception>();
      var c = Directory.GetFiles(@"c:\windows\assembly", "*.dll", SearchOption.AllDirectories).ToList()
          .ConvertAll(f => Path.GetFileNameWithoutExtension(f))
          .Where(f => !f.EndsWith(".ni"))
          .Distinct().ToList()
          .ConvertAll(f => { try { return Assembly.ReflectionOnlyLoad(f); } catch (Exception ex) { errors.Add(ex); return null; } })
          .Where(a => a != null)
          .SelectMany(a => { try { return a.GetTypes(); } catch (Exception ex) { errors.Add(ex); return new Type[] { }; } })
          .Where(t => targetType.IsAssignableFrom(t));
      

      祝你好运。

      【讨论】:

      • 我在写我的时候没有注意到 darin 的回答 - 与读取 c:\windows\assembly 中的文件相比,gacapi 项目听起来是一个更好的选择来获取程序集列表。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-16
      • 2011-10-24
      • 2018-07-01
      • 2010-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多