1

I have been given the task to write a technical specification (and later implement) a system that will be build on a few sub-modules. The sub-modules will be developed partly in parallel so I would really like to avoid restarting the whole system each time a plugin is added or updated. Since I have already used Simple Injector in another project I plan to use it for IoC in each sub-module. Instead of introducing MEF (Managed Extensibility Framework) or MAF (Managed AddIn Framework) in the core binding the modules together, my plan is to see if Simple Injector can be used for handling the modules as well.

My plan is to use a FileSystemWatcher to watch a plugin directory and when a change is detected either have Simple Injector do it's thing or perhaps roll my own solution. I have read the discussion here but I believe my use case is different.

Requirements:

  • The core system runs as a Windows service and restarting this all the time should be avoided
  • Each module is responsible for internally orchestrating the work that needs to be done (which can be a lot, hence the requirement for not restarting everything)
  • The whole system is event-based. Modules will emit events to an event bus so that other modules can react (do it's thing) based on the event. Modules will, however, be allowed to do things on a regular basis as well. F.x. one module listens for new files in a directory, parses the file and puts data in a database. Other modules might need to do something based on this new data. Another module does some periodical calculations.
  • All modules will share a common interface IModule that will enable the core system to start and stop (dispose) the module, perhaps along with a method to register the event bus if I can't find another way around that
  • On system restart (f.x. server restart) the core should, of course, be able to pick up all existing modules

To be able to dynamically load/reload assemblies I plan on running each module in a separate AppDomain.

Is this possible using Simple Injector? Any other thoughts? Perhaps something I haven't thought about.

Casper
  • 1,051
  • 1
  • 8
  • 21

2 Answers2

1

This is not something that DI Containers facilitate. They just compose object graphs. Seems to me you need to run isolated processes or app domains (otherwise it would be impossible to reload them).

This means that the DI Container will run inside that isolated domain (i.e. your module) a d within that module, you would use your container as you would always use it. This wouldn't be different with Simple Injector.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • I was afraid that that's what you would tell me I was looking into MAF and MEF when I stumbled upon someone who mentioned DI when talking about MEF and so I started looking for a solution that would not bring another framework into the equation (MEF). I guess I will have to do that or roll my own solution. Thank you for your time and help. I will come back to this question with an answer when I find the right solution – Casper Jun 08 '18 at 20:35
  • Btw. Any other thoughts /comments on my design proposal? – Casper Jun 08 '18 at 20:40
  • My real question is: do you really need this amount of flexibility? Still, with your system, I see no reason why the application should keep running. This is especially the beauty of using events that are stored in a durable queue: nobody will notice when you restart. Even if you restart 100x a day. I don't think frameworks like MEF and MAF are very suited for what it is you are trying to achieve. They handle plug-ins, but you are talking about complete bounded contexts here (complete applications), 'accidentally' running in the same process (but perhaps different app domain). – Steven Jun 10 '18 at 13:13
  • Thank you for the input. Perhaps you are right about the flexibility. Maybe my current proposal is over engineering the problem and just using DI on launch is enough (which means ignoring the "no restart" requirement). Actually I thought about putting each module in a separate process as well to keep it separated, but I know that separate process or app domain complicates communication a lot. I guess I will have to talk to my CTO about it... – Casper Jun 10 '18 at 20:43
  • Separate app domains do complicate communication. If, however, your only means of communication is through events (sent through a durable queue), this should be a no-brainer; you have complete freedom in running everything in one app domain, one process, one machine, or spread out over multiple machines. – Steven Jun 10 '18 at 21:11
0

So, based on the correspondence with Steven I decided to look at alternatives and talk to my CTO. This resulted in a completely different architecture (microservices - probably implemented as Azure Functions) communicating through a message bus (Azure Service Bus). This complies with all the requirements and (using Azure Functions) ensures that we only pay for computing power when events arises that should be handled.

Casper
  • 1,051
  • 1
  • 8
  • 21