Implement isolated plugins, runtime plugin load/unload #751
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Background
The core design of Anvil merges all
[ServiceBinding]
types from plugins and Anvil itself into a single container, which is then wired up by LightInject to correctly resolve all dependencies:This works really well for simple configurations, and for easily setting up service dependencies between plugins and anvil. E.g. if I want to use the
WindowManager
from the toolbox plugin, I can simply reference the plugin assembly and declare the dependency in my service class:One drawback to this approach is that all plugins + Anvil must be loaded and unloaded as one unit, making it impossible to toggle or configure them individually.
Isolated plugins
This PR introduces the concept of isolated plugins. An isolated plugin is configured by defining the
PluginInfoAttribute
on the plugin assembly:When a plugin is configured as isolated, it is given a dedicated container that cannot be used by other plugins or anvil when resolving dependencies:
The plugin container can use services from other plugins and anvil, but its own services cannot be used by other plugins.
This allows isolated plugins to be loaded/unloaded without disrupting anvil or other plugins that may be referencing it.
PluginManager API
The following methods have been exposed in the PluginManager to support runtime loading/unloading of plugins:
Disabled/Skipped plugins
Plugins may be disabled/prevented from loading by specifying
ANVIL_PLUGINNAME_SKIP=true
, replacing "PLUGINNAME" with the plugin that should not be loaded.Isolated plugins disabled this way may still be loaded from the
PluginManager
APIs.