【问题标题】:Retrieve Objects That Implement Interface From Across Several Assemblies从多个程序集中检索实现接口的对象
【发布时间】:2012-02-01 23:10:04
【问题描述】:

我想从解决方案文件夹中的多个程序集检索实现接口的实例化类的枚举。

我有以下文件夹结构(如果这有意义的话):

Solution
   -SolutionFolder
      - Project1
          - class implementing interface I would like to find
          - other classes

      - Project2
          - class implementing interface I would like to find
          - other classes

   -MainProject
      - classes where my code is running in which I would like to retrieve the list of classes

因此,如果正在实现的接口是ISettings,那么我想要一个IEnumerable<ISettings> 引用该接口的实例化对象。

到目前为止,我已经使用反射从已知的类名中检索实现接口的类:

IEnumerable<ISettings> configuration = 
                (from t in Assembly.GetAssembly(typeof(CLASSNAME-THAT-IMPLEMENTs-INTERFACE-HERE)).GetTypes()
                 where t.GetInterfaces().Contains(typeof(ISettings)) && t.GetConstructor(Type.EmptyTypes) != null
                 select (ISettings)Activator.CreateInstance(t)).ToList();

但这是一个单独的程序集,我实际上并不知道类名。

这可以使用反射来实现还是需要更多的东西?

【问题讨论】:

    标签: c# reflection assemblies


    【解决方案1】:

    只要您只是谈论加载到 AppDomain 中的程序集(它们必须是为了做您所追求的事情),您就可以使用这样的东西来遍历它们:

    AppDomain.CurrentDomain
             .GetAssemblies().ToList()
             .ForEach(a => /* Insert code to work with assembly here */);
    

    或者,如果您将它们加载到不同的 AppDomain 中,您可以使用实例来代替上面的 AppDomain.CurrentDomain

    【讨论】:

    • 感谢您的回答。但是,我的程序集最初不会加载到应用程序域中,并且我可能需要插入其他程序集,同时避免重新编译主项目(我在最初的问题中没有明确表示歉意)。
    • 您可以在运行时结合使用您问题中的代码、我的答案中的代码和Assembly.Load,将程序集动态加载到您的应用程序域中。你的插件只有在你加载它们时才能执行。
    【解决方案2】:

    为了解决这个问题,我在解决方案文件夹中设置了每个项目的构建后事件,以将其程序集复制到主项目 bin 文件夹中的 bin 文件夹中。

    构建后事件的设置类似于:

    copy "$(TargetPath)" "$(SolutionDir)MainProjectName\bin"
    

    然后我使用以下内容从这个 bin 目录中检索程序集文件名(感谢 Darin 的解决方案帖子 here):

    string[] assemblyFiles = Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"), "*.dll");
    

    然后我检索了实现接口 ISettings 的对象的实现:

    IEnumerable<ISettings> configuration = assemblyFiles.Select(f => Assembly.LoadFrom(f))
                    .SelectMany(a => a.GetTypes())
                    .Where(t => t.GetInterfaces().Contains(typeof(ISettings)) && t.GetConstructor(Type.EmptyTypes) != null)
                    .Select(t => (ISettings)Activator.CreateInstance(t));
    

    这允许我添加更多实现设置的项目,而无需重新编译主项目。

    此外,我看到的另一种选择是使用MEF,其中可以找到简介here

    【讨论】:

      猜你喜欢
      • 2014-08-17
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      • 2017-09-11
      • 2014-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多