Plug-in Architecture To Work in WinForms MVC + WPF MVVM + ASP.Net MVC + Mobile (Xamarin MVC/PhoneGap MVC) + Win 10 Universal App MVC
This is my attempt to implement a general plugin system to work in multiple platforms and multiple technologies, with the main intent is to increase shared projects to the max, over those platforms.
This is the first draft, and I will be going back and forth in it, while I implement it, till it gets fully functional, so it might change while it gets implemented.
I searched the internet to find a suitable plug-in architecture that’s general enough and not too complex, to work with multiple technologies/platforms, mainly:
- WinForms MVC
- WPF MVVM
- ASP.NET MVC
- Mobile (Xamarin/PhoneGap) MVC
- Win 10 Universal App MVC
As can be seen in these articles:
And after a lot of reading for several days, I decided to go with my own architecture. And decided to make it as an article in my blog and in CodeProject, and later on, in github.com, for sharing and collaboration with the community, to perfect it, and make it general enough for all, and to increase the sharing and benefit from the larger more beautiful minds out there, so please comment.
I quote what MSDN said about the need for a Plug-in system:
- To extend an application's functionality without the need to re-compile and distribute it to customers.
- To add functionality without requiring access to the original source code.
- The business rules for the application change frequently or new rules are added frequently.
And I add my own:
- Faster compilation time and smaller solutions as each plug-in will need only small number of references to other projects.
- Maximize reuse of the main business functionality over multiple UI/OS- platforms Technologies.
- Simplify each project, to the maximum extent.
- Help fellow developers to speed development on all platforms.
The Main Architecture
So here are the main pieces, and their main objectives:
This is the main project that will configure the main App Services:
And then, it will parse the plug-in folders:
|- ASP.NET MVC
|- Win 10 Universal App
Depending on the configuration/LocalDB file property:
- App_Platform: (WinForms, WPF, ASP.NET MVC, Mobile (Xamarin/PhoneGap), Win 10 Universal App)
It will get the .dll plugin for the main UI “
IMainForm”, that is set in the configuration/LocalDB:
"WinForms"_ MainUI: MainFormplugin.dll
And get from it the main form, and show it.
Then it will search for the
Authentication plugin, that is set in the configuration/
And get from it the
ILoginForm, and show it to the user.
And will search for .dlls that have a reference to
IPlugin, and create an instance of it, and pass to it the services, and call its “
It will have a service locater to find in all the plugins the required implementation of interfaces.
It will connect the
DBObjects, to the
ServerDB to get the list of
IForms to be given to
IMainForm, to show them, and to get all the
IComposable List, to know which
IForm they will be composed in.
Will have properties for the services, to be set by its constructor.
init” function, to make its internal unity container, fill itself with all classes inside the plug-in, from a utility class.
Plugin\WinForms\MainUI \ MainForm
Will get the names of the
IForm list from the “
Host”, which is the “
PluginManager”, and show them to the user, for my WinForms, they will be shown in a
GridList, and only get what the user is allowed to see, depending on the
On double clicking the name of the
IForm record, it will be sent to an activator, inside the
IAuthentication, to see if its authorized, and show it to the user.
If anything will need a
msgbox to be displayed, then it will be supplied by this plugin, by having an implementation to
IMsgBox, and setting it in the
Plugin\WinForms\MainUI \ MsgBox
This will implement the
IMsgBox interface that will be implemented by each platform, but in this specific plugin, it will be implemented for WinForms, which might be different all together in other platforms.
Services\DBLocal Previously DBInstance
There will be a local database (PCs SQL Server LocalDB, Mobile à SQLite), that will hold configurations per platform, maybe some/all error messages, and some caching.
The logger project will implement
ILogger interface, and gets injected to all plugins, this will make them free from referencing its library or CodeProject.
I am making it, use Enterprise Library Logging block: https://entlib.codeplex.com
Reason: Because of its good pluggable nature and multi platform support, and its configuration possibilities.
This project is for handling all exceptions at the UI plugins level, it will be responsible for formulating error/warning messages, and displaying them to the user, by giving it to the
IFormError that will be supplied by the “
MainUIPlugin”, which might be a WinForm/ASP.NET MVC/Xamarin/….
This will have validations for general datatypes like
time, or for logical types like
And it will take validation from plugins, that implement
This will supply English lingual translation for UI controls and also
Data, by implementing
ILingual, and there will be a configuration property to set the main language, and for each user, there will be [Main language/Secondary language] in his settings.
Configuration.Lingual= English Lingual Plugin.dll
UserA. Configuration.Lingual_Main= English Lingual Plugin.dll
UserA. Configuration.Lingual_Secondary= French Lingual Plugin.dll
Plugin\Services\ Authentication \SimpleUserAuthentication
This will implement the
IPrivilegeAccess for login checking, and checking for user access privileges, as this can be changed with other types of Authentications like “
RoleAuthentication”, by setting a wide application configuration property:
Services\Object Management: UIFormViewManager
This will manage All forms/Views, which are the screen UI elements in all UI plugins, in several ways, like opening them, configuring their Combo boxes or List Boxes, showing detail/list of their data, extra. [to be further detailed]
Services\Object Management\ UIComposableManager
This will have all composable controls/subview, that will be inserted in Forms.
Currently not well defined, thinking of making it use Rx observable/publisher style for registering/unregistering of events generated from UI/Domain objects.
Currently not well defined, thinking of making it offer executable commands for UI/Domain objects.
This will have all information about the POCO properties and their types, and linkes to other POCOs, maybe validations.
The Layers from POCO classes to UI classes
These will implement the MVC pattern/Repository pattern.
This will have the business classes, and they will inherit from the
Repository.Pattern.Ef6.Entity class, which implements the
IObjectState interface for managing the POCO object state, and will all implement the
INotifyPropertyChanged, so it will notify who uses it, of any internal changes, and
IValidatableObject for making the POCO validate itself, by calling a method in the “
Validation” project, that will search the DB for that POCO validations and uses them to validate it.
Where each main category will have its own project, like
This will have the mapping for the Entity framework 7 configurations of all POCO classes.
Where each main category will have its own project, like
This will be the mediator between using Linq on the DAL layer, and upper layers, so it will hide the implementation details from them.
Where each main category will have its own project, like:
As seen here:
Model Layer/Controller Layer
I will ease things up, and relate to:
This will be implemented in plug-ins, so we can have the app work in multiple platforms like Plugin\WinForms\PersonUI, InvoiceUI.
Currently, I am thinking of using SQL Server, for app persistence.
The directory structure of the architecture is as shown below:
Code will be published here and in github.com.
Points of Interest
- Further study and comments are welcome.
- Comments/Ideas/Fixes in all the above are welcome.
- And other things to brain storm are:
- Event engine/Observer Engine/Rx Engine
- An engine that will facilitate plug-ability in actions and events in all or most layers.
There are the following questions that I need to have answers for:
Q1: Should I use GUID as primary key for some tables, to minimize conflicts when upgrading to new versions?
My answers to some questions asked:
Other Q1: Why not use MEF?
A1: I prefer to have all my classes in their pure POCO style, and not adorn them with specifics of other tools like MEF, so that's why I am using a DI-IoC container, to manipulate them from outside, not from inside.
- v0.5.1: Tried to fix the pictures of the article + added "Other Q1"
- v0.5: Created the main architecture