C# 插件编程技术学习

定义插件接口

// PluginInterface.cs
// 插件的公用接口
// 编译命令:csc /target:library PluginInterface.cs

using System;

public interface IPlugin
{
// 插件名称
string Name
{
get;
}

// 实现插件功能的方法
object DoWork(object parameter);
}

  

定义插件宿主接口

// HostInterface.cs
// 插件宿主的公用接口
// 编译命令:csc /target:library HostInterface.cs

using System;
using System.Collections.Generic;

public interface IHost
{
// 已经装载的插件的集合
// path为存放插件的目录
List<IPlugin> Plugins
{
get;
}

// 装载所有实现了IPlugin接口的插件
// path为存放插件的目录,返回值为符合要求的插件的数量
int LoadPlugins(string path);

// 获取指定的插件
// name为插件的名称
IPlugin GetPlugin(string name);
}

  

编写插件

// Plugin1.cs
// 插件示例
// 编译命令:csc /target:library /r:PluginInterface.dll Plugin1.cs

using System;

public class Plugin1 : IPlugin
{
// 表示插件名的私有字段
private string name;

// 实现IPlugin的Name属性
public string Name
{
get
{
return name;
}
}

// 无参数的构造函数
public Plugin1()
{
name
= "Plugin1";
}

// 实现IPlugin的DoWork方法
public object DoWork(object parameter)
{
Console.WriteLine(
"================================================");
Console.WriteLine(name
+ ": " + parameter.ToString());
Console.WriteLine(
"================================================");
return parameter;
}
}

  

// Plugin2.cs
// 插件示例
// 编译命令:csc /target:library /r:PluginInterface.dll Plugin2.cs

using System;

public class Plugin2 : IPlugin
{
// 表示插件名的私有字段
private string name;

// 实现IPlugin的Name属性
public string Name
{
get
{
return name;
}
}

// 无参数的构造函数
public Plugin2()
{
name
= "Plugin2";
}

// 实现IPlugin的DoWork方法
public object DoWork(object parameter)
{
Console.WriteLine(
"================================================");
Console.WriteLine(name
+ ": " + parameter.ToString());
Console.WriteLine(
"================================================");
return parameter;
}
}

  

除了插件名不同之外,Plugin1与Plugin2的代码几乎完全相同

编写插件宿主程序

// Host.cs
// 宿主程序
// 编译命令:csc /r:HostInterface.dll /r:PluginInterface.dll Host.cs

using System;
using System.IO;
using System.Collections.Generic;
using System.Reflection;

public class Host : IHost
{
// 私有字段,存放所有已经装载的插件的集合
private List<IPlugin> plugins = new List<IPlugin>();

// 实现IHost的Plugins属性
public List<IPlugin> Plugins
{
get
{
return plugins;
}
}

// 实现IHost的LoadPlugins方法
public int LoadPlugins(string path)
{
// 获取指定目录中所有的程序集
string[] assemblyFiles = Directory.GetFiles(path, "*.dll");
// 判断每一个程序集是否实现了插件接口IPlugin
foreach (string file in assemblyFiles)
{
// 装载程序集
Assembly assembly = Assembly.LoadFrom(file);
// 检查程序集中每一个公开的类型
foreach (Type t in assembly.GetExportedTypes())
{
// 该类型是否类、是否实现了IPlugin接口?
if (t.IsClass && typeof(IPlugin).IsAssignableFrom(t))
{
// 创建实现了IPlugin接口的类的对象
IPlugin plugin = Activator.CreateInstance(t) as IPlugin;
// 添加到集合中
plugins.Add(plugin);
}
}
}

return plugins.Count;
}

// 实现IHost的GetPlugins方法
public IPlugin GetPlugin(string name)
{
foreach (IPlugin ip in plugins)
{
if (ip.Name == name)
return ip;
}
return null;
}

// 输入数量的安全方法
private static int InputNumber(string prompt)
{
Console.Write(prompt);
string s = Console.ReadLine();
int amount = 0;
try
{
amount
= Int32.Parse(s);
}
catch (Exception) // 捕获任何异常
{
Console.Write(
"输入的数值格式不正确,请重新输入!"); // 提示错误
amount = InputNumber(prompt); // 递归调用InputNumber
}
return amount;
}

// 入口点
static void Main()
{
// 创建Host对象
Host h = new Host();
// 装载插件
h.LoadPlugins(".");

// 显示所有已经装载的插件
Console.WriteLine("已经装载如下的插件:");
int i = 1;
foreach (IPlugin ip in h.Plugins)
{
Console.WriteLine(
"{0}. {1}", i++, ip.Name);
}

// 选择插件
int si = InputNumber("请选择一个插件(按Enter键输入):");

Console.WriteLine(
"\n");

// 执行插件的功能
IPlugin plugin = h.GetPlugin(h.Plugins[si-1].Name);
plugin.DoWork(
"从宿主程序调用。");
}
}

  

将上述代码编译成应用程序Host.exe。注意,插件宿主程序中同时使用了IHost接口和IPlugin接口,因此,必须同时是程序集HostInterface.dll和PluginInterface.dll。

posted @ 2011-09-13 14:14  Tammie-锴  阅读(1447)  评论(0编辑  收藏  举报