前言
插件式架构,一种全新的、开放性的、高扩展性的架构体系。插件式架构设计好处很多,把扩展功能从框架中剥离出来,降低了框架的复杂度,让框架更容易实现。扩展功能与框架以一种很松的方式耦合,两者在保持接口不变的情况下,可以独立变化和发布。基于插件设计并不神秘,相反它比起一团泥的设计更简单,更容易理解。
项目介绍
书写4个插件类库,分别传参实现“加减乘除”运算,调用插件的客户端采用Winform窗体程序。
目标框架:.NET Framework 4.6.1
项目架构和窗体布局:
客户端程序:
- PluginApp:反射调用插件
插件描述:
- PluginBase:规范插件的基类,定义抽象类,开发的插件的类需要继承此类,代表遵守这个规范。
- CustomPlugInA:实现加法的插件
- CustomPlugInB:实现减法的插件
- CustomPlugInC:实现乘法的插件
- CustomPlugInD:实现除法的插件
代码实现
插件基类
///
///插件基类
///
public abstract class Base
{
///
/// 插件名称
///
///
public abstract string Name();
///
/// 插件描述
///
///
public abstract string Desc();
///
/// 执行方法
///
/// 参数1
/// 参数2
///
public abstract string Run(int param1, int param2);
///
/// 版本
///
public string Version
{
get { return "1.0.0"; }
}
}
PlugInA
public class PlugInA: Base
{
public override string Name()
{
return "PlugInA";
}
public override string Desc()
{
return "加法";
}
public override string Run(int param1,int param2)
{
return (param1 + param2) + "";
}
}
}
PlugInB
public class PlugInB : Base
{
public override string Name()
{
return "PlugInB";
}
public override string Desc()
{
return "减法";
}
public override string Run(int param1, int param2)
{
return (param1 - param2) + "";
}
}
PlugInC
public class PlugInC : Base
{
public override string Name()
{
return "PlugInC";
}
public override string Desc()
{
return "乘法";
}
public override string Run(int param1, int param2)
{
return (param1 * param2) + "";
}
}
PlugInD
public class PlugInD : Base
{
public override string Name()
{
return "PlugInD";
}
public override string Desc()
{
return "除法";
}
public override string Run(int param1, int param2)
{
return (param1 / param2) + "";
}
}
客户端核心代码:
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
dgrvPlugins.AutoGenerateColumns = false;
}
List List = new List();
readonly string PlugInPath = Application.StartupPath + "PlugIns";
///
/// 载入插件
///
///
///
private void btLoadPlugins_Click(object sender, EventArgs e)
{
if (!Directory.Exists(PlugInPath))
{
Directory.CreateDirectory(PlugInPath);
}
List.Clear();
string[] files = Directory.GetFiles(PlugInPath);
foreach (string file in files)
{
if (file.ToLower().EndsWith(".dll"))
服务器托管网 {
try
{
Assembly assembly = Assembly.LoadFrom(file);
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.BaseType.FullName == "PlugInBase.Base")
{
object obj = assembly.CreateInstance(type.FullName);
string name = type.GetMethod("Name").Invoke(obj, null).ToString();
string desc = type.GetMethod("Desc").Invoke(obj, null).ToString();
string version = type.GetProperty("Version").GetValue(obj).ToString();
List.Add(new PluginModel
{
Name = name,
Desc = desc,
Version = version,
type = type,
Obj = obj
});
}
}
}
catch (Exception ex)
{
throw ex;
}
服务器托管网 }
}
dgrvPlugins.DataSource = new BindingList(List);
}
///
/// 打开插件目录
///
///
///
private void btOpenPluginDir_Click(object sender, EventArgs e)
{
Process.Start(PlugInPath);
}
///
/// 执行选中插件
///
///
///
private void btExcute_Click(object sender, EventArgs e)
{
//获取选择的插件信息
int index = dgrvPlugins.CurrentRow.Index;
object obj = List[index].Obj;
Type type = List[index].type;
//参数
object[] inParams = new object[2];
inParams[0] =Convert.ToInt32( dgrvPlugins.CurrentRow.Cells[2].Value);
inParams[1] = Convert.ToInt32(dgrvPlugins.CurrentRow.Cells[3].Value);
object value = type.GetMethod("Run").Invoke(obj, inParams);
MessageBox.Show(Convert.ToString(value),"结果",MessageBoxButtons.OK);
}
}
项目配置
插件生成配置
编译生成项目的时候需要注意,此处的调用插件是通过反射调用.dll中类和方法,所以首先要找到这个.dll的文件,所以此处我们在Winform客户端程序下建立一个存放类库dll的文件PlugIns
,在插件类库项目生成后事件命令中,填入如下命令:
copy /Y "$(TargetDir)$(ProjectName).dll" "$(SolutionDir)PlugIns"
以上命令代表,在项目的类库生成后,将类库copy到解决方案的路径子文件夹PlugIns
,也就是我们建立存放自定义插件的文件夹。当然,如果不怕麻烦,每次生成后,手动复制到此文件夹也可以,直接复制到客户端程序的..binPlugIns
文件夹下。
插件路径配置
全选这些类库,把这些类库设置为”如果较新则复制”,这样每次在编译客户端程序,如果自定义插件有更新,则同步会复制到bin
目录下
插件基类配置
插件基类提供了规范,需要在类库的生成后事件,添加命令:
copy /Y "$(TargetDir)$(ProjectName).dll" "$(SolutionDir)binDebug"
将生成的dll文件,拷贝到客户端程序的bin
路径下
调用演示
CustomPlugInA
CustomPlugInB
CustomPlugInC
CustomPlugInD
插件开发优缺点
- 把扩展功能从框架中剥离出来,降低了框架的复杂度,让框架更容易实现
- 宿主中可以对各个模块解析,完成插件间、插件和主程序间的通信。
- 插件开发的可扩展性,灵活性比较高,而且可以进行定制化开发。
缺点
-
每一个插件被编译成了dll,各模块无法单独运行,必须依托于主程序。
-
修改插件时,由于生成的是dll,无法快速直观的查看修改以及调试。
-
每一个插件必须依赖于某一个规范。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
一、前言 今天给大家带来一个非常好玩的js小demo,实现数值的动态变化!这个效果之前在清华大学的官网上见到过(现在他们把这个效果给取消了),之前觉得这个效果挺好玩的,这些天在复习js的时候,无意间见到了这效果,于是写了一个,想分享给大家。 效果如下: 那么它…