C#学习笔记28——C# 插件编程
2011-09-04 14:07
459 查看
最近也研究了下插件编程,网上的例子太少,而且不适合初学者。这里专门做了个简单易懂的例子,供大家学习,程序如有问题还望跟帖予以指教。
程序界面运行如下:
//==============================================================
首先,我们要定义一个插件接口,接口规范了插件内部类的程序结构,应实现的字段,属性,方法,事件。
using System;
using System.Collections.Generic;
using System.Text;
namespace IMsg
{ //这是插件必须要实现的接口,也是主程序与插件通信的唯一接口,
//换句话说,主程序只认识插件里的这些方法
public interface IMsgPlug
{
void OnShowDlg();
string OnShowInfo();
}
}
再者,需要实现接口在主程序内部的处理过程,包括载入插件,获取插件内部的被接口规范了的字段,属性,方法,事件。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.Collections;
using IMsg;
namespace MsgBoxMain
{
public partial class FormMain : Form
{
public ArrayList plugins = new ArrayList();
public FormMain()
{
InitializeComponent();
}
//载入插件
private void LoadAllPlugins()
{
//获取指定插件目录下的所有文件的文件名
string[] files = Directory.GetFiles(Application.StartupPath + @"\plugins");
//遍历该文件名集合
foreach (string file in files)
{ //检索出文件名以.dll结束的文件
if (file.Substring(file.LastIndexOf(".")) == ".dll")
{
try
{ //载入dll
Assembly ab = Assembly.LoadFile(file);
//获得载入的dll中的所有类
Type[] tempTs = ab.GetTypes();
//遍历该类集合
foreach (Type tp in tempTs)
{
//如果某些类实现了预定义的IMsg.IMsgPlug接口,则认为该类适配与主程序(是主程序的插件)
if (IsValidPlugin(tp))
{ //实例化该类,并将对象装入动态数组plugins
plugins.Add(ab.CreateInstance(tp.FullName));
//将该类型名载入列表框内
ListItems.Items.Add(tp.Name.ToString());
}
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString(), "加载插件出错", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
//判断模块的类是否满足预定义接口
private bool IsValidPlugin(Type t)
{
bool ret = false;
Type[] interfaces = t.GetInterfaces();
foreach (Type theInterface in interfaces)
{
if (theInterface.FullName == "IMsg.IMsgPlug")
{
ret = true;
break;
}
}
return ret;
}
//调用插件内的方法
private void button2_Click(object sender, EventArgs e)
{
//获取列表框内被选择的项
string itemStr = ListItems.SelectedItem.ToString();
if(ListItems.SelectedIndex >= 0)
{
if (itemStr == "myConsole")
{ //调用存储在动态数组plugins里面的插件对象的OnShowInfo方法
string msgInfo = ((IMsgPlug)plugins[ListItems.SelectedIndex]).OnShowInfo();
MessageBox.Show(msgInfo, "MYPlugin1", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else if (itemStr == "MYDlg")//调用存储在动态数组plugins里面的插件对象的OnShowDlg方法
{
((IMsgPlug)plugins[ListItems.SelectedIndex]).OnShowDlg();
}
}
else
MessageBox.Show("请先选择列表框里的插件项", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
private void button1_Click(object sender, EventArgs e)
{
try
{ //载入插件
LoadAllPlugins();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
最后,编写插件类库,实现接口的属性,方法,事件。
//程序集(dll)内部的一个类1,该类实现了插件接口
using System;
using System.Collections.Generic;
using System.Text;
using IMsg;
namespace MYPlugin1
{ //实现插件接口
public class myConsole : IMsgPlug
{
public void OnShowDlg() {}
public string OnShowInfo()
{
return "调用了插件1的OnShowInfo方法!";
}
}
}
//程序集(dll)内部的一个类2,该类实现了也插件接口
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using IMsg;
namespace MYPlugin1
{ //实现插件接口
public partial class MYDlg : Form, IMsgPlug
{
public MYDlg()
{
InitializeComponent();
}
//=============================================
public string OnShowInfo() { return null; }
public void OnShowDlg()
{
this.Show();
}
//=============================================
}
}
总结: 通过反射以及接口使C#下的插件编程变得容易,我们在接口中定义的字段,属性,方法,事件是在插件里面被实现的,是在主程序里被解析的。主程序通过公共的接口访问插件。
源码地址:
pickup.mofile.com/4563655561281219
提取码 4563655561281219
C# 插件构架实战
http://www.cnblogs.com/wayfarer/articles/28537.html
程序界面运行如下:
//==============================================================
首先,我们要定义一个插件接口,接口规范了插件内部类的程序结构,应实现的字段,属性,方法,事件。
using System;
using System.Collections.Generic;
using System.Text;
namespace IMsg
{ //这是插件必须要实现的接口,也是主程序与插件通信的唯一接口,
//换句话说,主程序只认识插件里的这些方法
public interface IMsgPlug
{
void OnShowDlg();
string OnShowInfo();
}
}
再者,需要实现接口在主程序内部的处理过程,包括载入插件,获取插件内部的被接口规范了的字段,属性,方法,事件。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.Collections;
using IMsg;
namespace MsgBoxMain
{
public partial class FormMain : Form
{
public ArrayList plugins = new ArrayList();
public FormMain()
{
InitializeComponent();
}
//载入插件
private void LoadAllPlugins()
{
//获取指定插件目录下的所有文件的文件名
string[] files = Directory.GetFiles(Application.StartupPath + @"\plugins");
//遍历该文件名集合
foreach (string file in files)
{ //检索出文件名以.dll结束的文件
if (file.Substring(file.LastIndexOf(".")) == ".dll")
{
try
{ //载入dll
Assembly ab = Assembly.LoadFile(file);
//获得载入的dll中的所有类
Type[] tempTs = ab.GetTypes();
//遍历该类集合
foreach (Type tp in tempTs)
{
//如果某些类实现了预定义的IMsg.IMsgPlug接口,则认为该类适配与主程序(是主程序的插件)
if (IsValidPlugin(tp))
{ //实例化该类,并将对象装入动态数组plugins
plugins.Add(ab.CreateInstance(tp.FullName));
//将该类型名载入列表框内
ListItems.Items.Add(tp.Name.ToString());
}
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString(), "加载插件出错", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
//判断模块的类是否满足预定义接口
private bool IsValidPlugin(Type t)
{
bool ret = false;
Type[] interfaces = t.GetInterfaces();
foreach (Type theInterface in interfaces)
{
if (theInterface.FullName == "IMsg.IMsgPlug")
{
ret = true;
break;
}
}
return ret;
}
//调用插件内的方法
private void button2_Click(object sender, EventArgs e)
{
//获取列表框内被选择的项
string itemStr = ListItems.SelectedItem.ToString();
if(ListItems.SelectedIndex >= 0)
{
if (itemStr == "myConsole")
{ //调用存储在动态数组plugins里面的插件对象的OnShowInfo方法
string msgInfo = ((IMsgPlug)plugins[ListItems.SelectedIndex]).OnShowInfo();
MessageBox.Show(msgInfo, "MYPlugin1", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else if (itemStr == "MYDlg")//调用存储在动态数组plugins里面的插件对象的OnShowDlg方法
{
((IMsgPlug)plugins[ListItems.SelectedIndex]).OnShowDlg();
}
}
else
MessageBox.Show("请先选择列表框里的插件项", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
private void button1_Click(object sender, EventArgs e)
{
try
{ //载入插件
LoadAllPlugins();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
最后,编写插件类库,实现接口的属性,方法,事件。
//程序集(dll)内部的一个类1,该类实现了插件接口
using System;
using System.Collections.Generic;
using System.Text;
using IMsg;
namespace MYPlugin1
{ //实现插件接口
public class myConsole : IMsgPlug
{
public void OnShowDlg() {}
public string OnShowInfo()
{
return "调用了插件1的OnShowInfo方法!";
}
}
}
//程序集(dll)内部的一个类2,该类实现了也插件接口
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using IMsg;
namespace MYPlugin1
{ //实现插件接口
public partial class MYDlg : Form, IMsgPlug
{
public MYDlg()
{
InitializeComponent();
}
//=============================================
public string OnShowInfo() { return null; }
public void OnShowDlg()
{
this.Show();
}
//=============================================
}
}
总结: 通过反射以及接口使C#下的插件编程变得容易,我们在接口中定义的字段,属性,方法,事件是在插件里面被实现的,是在主程序里被解析的。主程序通过公共的接口访问插件。
源码地址:
pickup.mofile.com/4563655561281219
提取码 4563655561281219
C# 插件构架实战
http://www.cnblogs.com/wayfarer/articles/28537.html
相关文章推荐
- C# 插件编程技术学习
- 深入.NET平台和C#编程 第三章 学习笔记
- 黑马程序员之C#编程基础学习笔记:用while continue实现计算1到100之间的除了能被7整除之外所有整数的和。
- C#网络编程学习笔记1
- 【JAVAWEB学习笔记】28_jquery加强:json数据结构、jquery的ajax操作和表单校验插件
- 黑马程序员之C#编程基础学习笔记:用while break实现要求用户输入用户名和密码,只要不是admin,888888就一直提示要求重新输入。
- C#2005 .NET3.0高级编程学习笔记———.NET体系结构
- c#网络编程学习笔记01_委托
- 黑马程序员之C#编程基础学习笔记:编写聊天机器人,如果向机器人说"今天天气怎么样?"则回答天气,如果向机器人说"88",则回答再见“。
- C#2005 .NET3.0高级编程学习笔记————接口
- 【卷土重来之C#学习笔记】(二)c#编程概述
- 线程处理(C# 编程指南)学习笔记1
- 学习笔记之在 LINQ 外部使用 Lambda 表达式(C# 编程指南)
- c#网络编程学习笔记02_Tcp编程(上)
- 黑马程序员之C#编程基础学习笔记:从一个整数数组中取出最大的整数。
- C#学习笔记二:并行编程基础:在 PLINQ 和 TPL 中的 Lambda 表达式
- C#可扩展编程之MEF学习笔记(三):导出类的方法和属性
- 黑马程序员之C#编程基础学习笔记:让用户输入两个数,打印出两个数的和。
- 黑马程序员之C#编程基础学习笔记:计算一个整数数组的所有元素的和。
- C#学习笔记(28)——委托排序(2)自定义排序