# 概述
为了增加程序的可扩展性,在主程序中添加了插件框架,以保证能在避免最大限度修改主体模块的基础上,添加新的功能和代码。
实现插件模块需要定义一个公共接口 PluginInterface,主程序通过这个接口来实现对插件具体功能的调用。插件模块需要在自行实现接口,并且传入所需要的常量值。
插件会在窗体初始化过程中被加载到进程空间中,并调用 Init (),在主窗体控件完成初始化和加载后调用 OnLoad (),之后框架会判断该插件是否具为周期执行,如果是则为其创建一个时钟并绑定周期事件为 RunLoop ()。主程序执行过程中会根据当前执行位置调用插件中满足当前 flag 的函数,此部分待后续补充。
具体实现流程如图:

# 插件接口的实现方式
接口定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
public interface IPlugin { string Name { get; } string RunFlag { get; } Dictionary<string, object> Attributes { get; set; } Information Info { get; } bool IsLoop { get;} int Interval { get; } string Hello() void Run(); void RunLoop(); void OnLoad(); void Init(Control control = null); void RegisterCallBackFunc(Action a); void OnDestory(); }
|
具体代码实现包含几个部分:
- 引入接口模块,并继承接口
- 配置各类属性常量
- 实现所有的事件触发函数
- 设置所需要的触发事件
插件的具体实现举例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| namespace PluginChart {
#region 插件需要继承IPlugin接口 public class PChart : IPlugin { public string Name { get { return "绘图插件"; } }
public Information Info { get { Information info = new Information(); info.Name = "绘图插件"; info.CreateDate = "2022-10-03"; info.ModifyDate = "2022-10-13"; info.Version = "0.2.0"; info.Author = "Liu Chongyang"; info.Copyright = "Copyright © 2020-2022 Joee Cto. © \n All rights reserved."; return info;
} } public bool IsLoop { get { return true; } } public int Interval { get { return 100; } }
public Dictionary<string, object> Attributes { get; set; }
public string RunFlag { get { return null; } }
public string Hello() { return "用于实现绘制数据图表的插件"; } #endregion
#region 定义需要用到的变量 public int index = 0; Control uControl; Panel panel; System.Windows.Forms.DataVisualization.Charting.Chart chart;
Form MainWnd; TabPage tabPage_chart; public List<string> DefectTypes; #endregion
#region 各类插件的实现 public void Init(Control control) { Attributes = new Dictionary<string, object>(); MainWnd = (Form)control; uControl = new UserControl1(); panel = (Panel)uControl.Controls.Find("panel_global", true)[0]; chart = (Chart)uControl.Controls.Find("chart1", true)[0]; chart.Series.Clear(); DefectTypes = new List<string>(); }
public void OnDestory() {
}
public void OnLoad() { Console.WriteLine($"Onload excute : {Name}"); Run(); }
public void RegisterCallBackFunc(Action a) { throw new NotImplementedException(); }
public void Run() { tabPage_chart = (TabPage)MainWnd.Controls.Find("tabPage_chart", true)[0]; tabPage_chart.Controls.Clear(); tabPage_chart.Controls.Add(panel); } public void RunLoop() { ... } #endregion
|
# 插件的调用方式
主程序在启动时会检查 plugins 目录下有无符合条件的插件,具体条件为:
- 扩展名为 .dll 或 ***.plugin ***
- 是 .NET Framework >= 4.7 的扩展库
- 包含 IPlugin 的接口实现
当找到插件文件时,主程序会按前文所述方式进行插件初始化和调用,于是插件便可以实现在不修改主程序代码的情况下,对于主程序窗体的控件控制和修改。
如下图,是绘图插件中的自定义控件。

1 2 3 4 5 6 7
| public void Run() { tabPage_chart = (TabPage)MainWnd.Controls.Find("tabPage_chart", true)[0]; tabPage_chart.Controls.Clear(); tabPage_chart.Controls.Add(panel); }
|
经过如上代码的操作后,自定义控件就可以添加到主程序窗体中,并且根据主程序中的数据来生成图表 (具体实现见开发日志 10.12)。
