I had created this configuration application in Windows Form using reflection where I used a Windows Form having only one control (TabControl) and I was loading plugins (.dlls) in the blank application.
Below are the steps to create the Configuration App Solution.
Step 1
Create a blank solution with the name "ConfigurationManager Application".
Step 2
Add a Windows application project with the name "ConfigurationApplication" in the solution.
Step 3
Add a class library project called “CommonModule.Lib".
Step 4
Add a class library project called "ConnectDb.Lib".
Finally, the solution will look something like this.
Now, we will write some code but before that, we need to create 2 folders "Config" and "MenuPlugins" inside the Config folder. For my convenience, I have created this inside the debug directory of the bin folder and I am mapping it with the below line of code.
string menuPluginPath = Application.StartupPath + "\\Config\\MenuPlugins"
The Config folder contains "CustomPluginSequence.xml" which contains a sequence of plugins to load in the application.
- <?xml version="1.0" encoding="utf-8" ?>
- <Config>
- <Plugin key="SQLPlugin">DBConnect.LIB.dll</Plugin>
- </Config>
Now, we will add an interface called IMenuPluginService.cs in the project ConfigurationApp.COMMON and write the below properties and method.
- namespace ConfigurationApp.COMMON
- {
- public interface IMenuPluginService
- {
- string PluginName { get; }
- TabPage ApplyMenuPlugin(TabPage tabMenuPlugin);
- UserControl UsrServiceControl { get; }
- }
- }
The next step is to add a UserControl called UserDBConnectControl where we are going to add the controls and the functionlty of the screen according to our usage. For my instance, I have created a SQL Server authentication screen. For reference, see the image below.
The next step is to add a class file called UserSQLControl.cs. In this class file, I have written the code to add the name of the Menu. Initialize the screen to the userControl and add the screen to the TabPage which will be loaded at run time by the TabControl which is there in the Configuration Application Windows project.
I have also implemented IMenuPluginService.cs interface to get all the properties and methods but before that, we need to provide the reference from ConfigurationApp.COMMON project to get the interface namespace. The code for this is written below.
- using ConfigurationApp.COMMON;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
-
- namespace DBConnect.LIB
- {
- public class UserSQLControl : IMenuPluginService
- {
- UserControl _userDatabaseControl;
- public string PluginName
- {
- get
- {
- return "Connect SQL Server";
- }
- }
-
- public UserControl UsrServiceControl
- {
- get
- {
- if (_userDatabaseControl == null)
- {
- _userDatabaseControl = new UserDBConnectControl();
- }
-
- return _userDatabaseControl;
- }
- }
-
- public TabPage ApplyMenuPlugin(TabPage tabMenuPlugin)
- {
- tabMenuPlugin.Text = PluginName;
- tabMenuPlugin.Controls.Add(UsrServiceControl);
-
- return tabMenuPlugin;
- }
- }
- }
Now, the next and final step is to add the code in ConfigurationForm.cs of ConfiruationManagerlibrary which is of a blank Windows Form.
Below is the code.
- using ConfigurationApp.COMMON;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- using System.Xml;
-
- namespace ConfigurationManager
- {
- public partial class ConfigurationForm : Form
- {
- string menuPluginPath = Application.StartupPath + "\\Config\\MenuPlugins";
- string customSetMenuXML = Application.StartupPath + "\\Config\\CustomPluginSequence.xml";
-
- IMenuPluginService IMPlugins;
-
-
- public ConfigurationForm()
- {
- InitializeComponent();
- }
-
- private void ConfigurationForm_Load(object sender, EventArgs e)
- {
-
- DirectoryInfo directoryInfo = new DirectoryInfo(menuPluginPath);
- XmlDocument document = new XmlDocument();
- document.Load(customSetMenuXML);
- XmlNodeList xmlNodeList = document.GetElementsByTagName("Plugin");
- int dllCount = xmlNodeList.Count;
- string[] files = new string[dllCount];
-
- for (int i = 0; i < xmlNodeList.Count; i++)
- {
- files[i] = menuPluginPath + "\\" + xmlNodeList[i].InnerText.ToString();
- }
-
- foreach (string file in files)
- {
- Assembly assembly = Assembly.LoadFrom(file);
-
- foreach (Type type in assembly.GetTypes())
- {
- if (type.GetInterfaces().Contains(typeof(IMenuPluginService)))
- {
- TabPage tabPage = new TabPage();
-
- IMPlugins = Activator.CreateInstance(type) as IMenuPluginService;
- tabPage = IMPlugins.ApplyMenuPlugin(tabPage);
- MenuTabs.Controls.Add(tabPage);
-
- }
- }
-
- }
- }
- }
- }
In the above code, I have used reflection to load the Plugin DLL as tab pages (However, here, for example, I have created only one Plugin DLL ) and added the tab pages in the Tab control of Windows form.
Note
As the plugin libraries could be built randomly, I have mapped the sequence from the sequence XML which I am getting by using the below line of code in the Form Load event.
- XmlDocument document = new XmlDocument();
- document.Load(customSetMenuXML);
- XmlNodeList xmlNodeList = document.GetElementsByTagName("Plugin");
- int dllCount = xmlNodeList.Count;
- string[] files = new string[dllCount];
- for (int i = 0; i < xmlNodeList.Count; i++)
- {
- files[i] = menuPluginPath + "\\" + xmlNodeList[i].InnerText.ToString();
- }
Next, I am looping from the correct sequence and from the reflection I am loading in the tab control.
I hope I was able to show you how to create a simple Windows application using the plugin architecture with reflection.
For reference, I am also attaching the code sample in this blog.
Note 2
I have not written the functionality of SQL screen as this is out of the scope of this example.