I'm developing a .Net desktop app that interacts with scientific instruments. There are a number of variations of this instrument, each with different features, components, etc, so I've come up with a plugin/modular architecture where a "module assembly" contains all of the necessary business logic, UI, etc. to interact with that hardware component/feature.
Currently I have one solution that contains everything - the "core" application project, common libraries, plus the "module" projects. The idea is that we install the whole lot to a customer site (rather than cherry-picking which DLLs they need), and "activate" the relevant modules using a config file that contains a list of required modules.
The main application project loads the modules using Castle Windsor, using an AssemblyFilter and a custom InstallerFactory. It searches each module assembly looking for a class implementing IWindsorInstaller
and decorated with a particular custom attribute (which has a property containing the module name). The module's installer will only be run if the attribute's module name is one of those requested. These installer classes are responsible for registering everything needed by that module with Windsor (business logic, views, view models, etc.).
This solution works fine in my proof of concept, however I can see a scenario where two or more modules are functionally very similar, and will therefore need to share common code. Let's say I have projects "ModuleA" and "ModuleB", and their Windsor installers registers the same IFooService
class in project "ClassLibraryX". The app will fall over because IFooService has been reigstered twice, and Windsor won't know which one to resolve when requested by a constructor.
What's the best way to handle this? Thoughts so far:-
- Find out if a particular component has already been registered with Windsor. This feels hacky (if possible at all)
- Register components using a name, but how do I request a named instance with constructor injection?
- In each module project create a new interface, such as
public interface IModuleAFooService : IFooService
, and register/use this throughout the project (rather thanIFooService
).
Any thoughts?
Edit: in fact Windsor won't fall over when it tries to resolve IFooService
. It will fall over when the second module attempts to register the same interface/concrete implementation!