Search code examples
visual-studiodependency-injectionmsbuildnugetinversion-of-control

How do you manage dependencies with inversion of control?


I am a small software developer who builds a plugin-based app. Each plugin is its own assembly and references the main assembly like so:

  • Plugin 1 references nuget packages and Application Core.dll
  • Plugin 2 references nuget packages and Application Core.dll

At run time, the main assembly loads all the assemblies in its current folder and enumerates them for plugins. Right now, all my projects build to the same folder. I like doing that because I can just press F5 to run my solution in Visual Studio. This is also nice because I can just disable a project in the solution if I don't want to run that plugin.

Some plugins now require a specific version of a nuget package. For example:

  • Plugin 1 requires System.Net.Http 4.0.0 or above
  • Plugin 1 requires System.Net.Http 4.3.4 or above

When I build my project, sometimes plugin 2 builds first which means that plugin 1 or 2 will overwrite system.net.http 4.3.4 with version 4.0.0.

What is the best way for me to avoid overwriting DLLs with older versions but still have the ease-of-development that I'm used to?


Solution

  • One solution, which you may not like, is to stop using dynamic loading. If your app uses Plugin 1 and Plugin 2, make them NuGet or project references and let the build system figure out minimum versions of all common packages for you. You will also no longer need to change all the build output paths to get an easy development experience. Just use feature-flags/configuration to allow customers to choose the features they want, rather than adding/deleting dlls.

    Another option is to keep each plugin in their own folders with all of their own dependencies and the main program loads plugins in different App Domains. this only works on .NET Framework, not .NET Core, but it does have the advantage that a plugin that crashes has less chance of crashing the whole app. the program may be able to detect a crashed plugin/app domain and unload it. But app domains are almost like using different processes and you have inter-domain communication issues (everything must be serialisable)