C# 插件式开发示例
本文介绍.net开发中利用反射进行插件式开发的示例。
例子很简单,如下图所示的form中有一个picturebox,通过插件来对picturebox的Image进行编辑。
所有的插件必须实现主程序定义的接口,主程序相当于一个框架,具体的功能实现则由客户提供的插件完成,下面是解决方案的框架:
项目IPlug定义插件接口。DrawRectPlug和DrawTextPlug分别为两个具体的插件。
下面是我们定义接口
using System;
using System.Drawing;
using CommonSDK;
namespace IPulg
{
public interface IPlug
{
/// <summary>
/// 发布事件
/// </summary>
event EventHandler<EventArgs<Image>> Handled;
/// <summary>
/// 插件按钮图标
/// </summary>
/// <returns></returns>
Bitmap GetToolIcon();
/// <summary>
/// 处理图像,结果通过事件发布
/// </summary>
/// <param name="img"></param>
/// <param name="arg"></param>
void DoHandlImage(Bitmap img, object arg);
}
}
STP 1 完成主界面加载插件的框架
我们规定插件的存放地址为bin/Debug/plugs目录下,因此我们通过System.IO.Directory.GetFiles方法找到该目录下的所有插件,通过反射生成插件的实例。
为了避免手工将插件复制到bin/Debug/plugs文件夹下,在DrawRectPlug和DrawTextPlug两个项目的生成事件中加下以下命令:
copy /V "$(TargetDir)$(TargetName).dll" "$(TargetDir)..\..\..\WindowsFormsExtents\bin\Debug\plugs"
以下是加载插件的核心代码
private void Form1_Load(object sender, EventArgs e)
{
string[] plugDlls = System.IO.Directory.GetFiles(System.Windows.Forms.Application.StartupPath + @"\plugs", "*.dll");
foreach (string dll in plugDlls)
{
Assembly a = Assembly.LoadFrom(dll);
System.Type[] types = a.GetTypes();
foreach (System.Type type in types)
{
System.Type[] interfaces = type.GetInterfaces();
if (type.GetInterface("IPlug") != null)
{
//IPulg.IPlug p = Activator.CreateInstance(type) as IPulg.IPlug;
//Bitmap img = p.GetToolIcon();
//System.Windows.Forms.ToolStripButton toolItem = new ToolStripButton(img);
//toolItem.Click += (c, e) =>
//{
// pictureBox1.Image = p.DoHandlImage((Bitmap)pictureBox1.Image, null);
//};
//toolStrip1.Items.Add(toolItem);
IPulg.IPlug plug = Activator.CreateInstance(type) as IPulg.IPlug;
plug.Handled += new EventHandler<CommonSDK.EventArgs<Image>>(p_Handled);
Bitmap img = plug.GetToolIcon();
System.Windows.Forms.ToolStripButton toolItem = new ToolStripButton(img);
toolItem.Click += new EventHandler(toolItem_Click);
toolItem.Tag = plug;
toolStrip1.Items.Add(toolItem);
}
}
}
}
STP2、开发插件
1、DrawRectPlug
这个插件的功能是在图片上填充一个黑色的矩形框,矩形框的位置已被程序写死。为了能够被主程序正确加载,DrawRectPlug 需要实现Iplug接口。
public class DrawRectPlug : IPulg.IPlug {
public event EventHandler<EventArgs<Image>> Handled;
public Bitmap GetToolIcon()
{
return Properties.Resources.Screenshot;
}
public void DoHandlImage(Bitmap img, object arg)
{
using (Graphics g = Graphics.FromImage(img))
{
g.FillRectangle(Brushes.Black, new Rectangle(0, 0, 100, 100));
Handled(this, new EventArgs<Image>(img));
}
}
}
2、DrawTextPlug插件略为复杂一点,它的功能是在图片上打印一段自定义的字符串,而允许用户指定其字体及大小
public class DrawTextPlug:IPulg.IPlug {
public event EventHandler<EventArgs<Image>> Handled;
public Bitmap GetToolIcon()
{
return Properties.Resources.Writing;
}
public void DoHandlImage(Bitmap img, object arg)
{
using (TextInputFrm frm = new TextInputFrm())
{
frm.ShowDialog();
using (Graphics g = Graphics.FromImage(img))
{
g.DrawString(frm.textBox1.Text, frm.fontDialog1.Font, Brushes.AliceBlue, 10, 10);
if (Handled != null)
Handled(this, new EventArgs<Image>(img));
}
}
}
}
程序运行效果图

浙公网安备 33010602011771号