检索跨多个程序集实现接口的对象

发布于 2025-01-01 12:58:11 字数 1034 浏览 3 评论 0原文

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

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

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 引用实例化对象该接口的。

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

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();

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

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

I would like to retrieve an enumeration of instantiated classes that implement an interface from across several assemblies within a solution folder.

I have a the following folder structure (if this makes sense):

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

Therefore, if the interface being implemented is ISettings, then I would like an IEnumerable<ISettings> referencing instantiated objects of that interface.

So far, I have used reflection to retrieve the classes that implement the interface from a known class name:

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();

but this is a single assembly and I will not actually know the class names.

Can this be achieved using reflection or does it require something more?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

喜爱纠缠 2025-01-08 12:58:11

只要您只谈论加载到 AppDomain 中的程序集(它们必须是为了执行您想要的操作),您就可以使用类似的方法来迭代它们:

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

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

As long as you're only talking about Assemblies that are loaded into an AppDomain (which they'll have to be in order to do what you're after), you could use something like this to iterate through them:

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

Or if you have them loaded in a different AppDomain, you could use an instance in the place of AppDomain.CurrentDomain above.

东风软 2025-01-08 12:58:11

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

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

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

然后,我使用以下命令从此 bin 目录中检索程序集文件名(归功于 Darin 的解决方案帖子 此处):

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,可以在其中找到介绍

To resolve this issue, I set the post build event of the each project in the solution folder to copy its assembly to the bin folder in the main projects bin folder.

The post build event was set similar to:

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

Then I used the following to retrieve the assembly file names from this bin directory (credit to Darin for his solution post here):

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

Then I retrieved implementations of the objects implementing the interface ISettings using:

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

This allows me to add further projects that implement settings without recompiling the main project.

Additionally, one alternative I looked at was to use MEF where an introduction can be found here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文