Simple Plugin System based on Ninject and MVVM Light
My goal was to develop a simple but useful plugin system for my future developments. I wanted to keep/to have:
- Ninject power and flexibility
- Smooth animations
- Modularity (development & code)
- Fast “menu” system
The PluginSystem assembly contains the plugin base class, the view model base class and an animated content control.
PluginBase class :
This class force plugins to expose a user interface, an name (for menu printing in this case) and force overriding OnActivate and OnDeactivate methods.
PluginViewModelBase class :
This class is a simple layer over ViewModelBase defined in MVVM Light. The main difference is that it embeds the reference of the parent plugin. With this reference, the plugin can easily access to injected values for example.
AnimatedContentControl class :
This usercontrol works like a commn ContentControl. There is one difference : if you change the content, it will animate it.
You can set AnimatedContent for the content, Delay, EasingFunction and Transition properties to customize the transition when you change the content.
Main application side
You can use the plugin system to get a dynamic menu:
- You can create a Ninject module for declaring plugin bindings.
- Once done, we get all registered plugins by using Ninject Kernel
- You set the list in your viewmodel
- You bind the list to the view
Last step is to bind the selected item’s user control to a content control (or an animated content control).
You can also use the plugin system to get static region system.
Defining a new Plugin
You need to create a new class library. Include some WPF libraries (System.Xaml, PresentationCore, PresentationFramework) and create a plugin definition file and a pluginVM file.
In this plugin file sample, you can set the “MainPart” property, create the view model and set it to the datacontext. Here is a sample:
With this system you can keep “blendability” by using “Sample data” system from Blend. You will have your view model with design mode detection and capability to set custom data.
Ninject power and flexibility
Based on Ninject system, you keep all the power of Ninject. For example :
This module defines 3 plugins but also define sorting parameters based on “Name”
You can use this module for extracting only “FirstScreenable” plugins
(Plugin3 is a dependency for Plugin2 it must not be printed on the first screen)
On the other hand, you can rely on Ninject to inject something else than plugins.
Thanks to the AnimatedContentControl, if you change the “AnimatedContent” property, you automatically start an animation. You can also see/try these animations inside Blend.
Modularity (development & code)
As you can see, the main application is perfectly separated from plugins. Each team can work on a plugin without interact with other plugins.
Why not using PRISM
I have tried Prism during 20 minutes and I was not able to create a simple plugin system based on it. Moreover Prism4 documentation pdf file is more than 352 pages (too much to read for a simple modularity system). One of the best practice is KISS, keep it stupid simple! By the way, this simple plugin system took me less than 30 minutes to create !
All sources are available for WPF here : PluginSystem.zip Contact me if you need a port in Silverlight 🙂