在平常的应用开发过程当中,插件化的软件更容易维护与扩展,插件作者只需要遵循指定的接口规范即可快速为软件添加新的功能。而在C#当中我们更能够轻松实现上述的功能,首先我们定义一个软件与插件所遵循的接口:
1
2
3
4
|
public interface IPlug
{
public int Func1(int a,int b);
}
|
之后我们新建一个类库,用于实现我们的插件功能,我们仅需要在类库中实现上述接口即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/*加法插件*/
public class addclass : IPlug
{
public int Func1(int a,int b)
{
return a+b;
}
}
/*减法插件*/
public class subclass : IPlug
{
public int Func1(int a,int b)
{
return a-b;
}
}
|
现在我们有两个插件了,那么我们怎么才能在主程序当中动态加载这些插件并且调用呢?
这里我们就需要用到C#的反射特性了,通过反射我们能够知道一个对象他有什么字段,有什么方法。
我们来编写一个插件管理类,叫做PlugManager.
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
|
public static class PlugManager
{
// 用于存放加载成功的插件
public static List<IPlug> m_PlugsList = new List<IPlug>();
public static int Load()
{
m_PlugList.Clear();
// 检测存放插件的目录是否存在
if (!Directory.Exists(Environment.CurrentDirectory + @"\Plugins")) return 0;
string[] files = Directory.GetFiles(Environment.CurrentDirectory + @"\Plugins");
foreach(string file in files)
{
string ext = file.Substring(file.LastIndexOf(".")); // 获得文件后缀
if (ext != ".dll") continue;
try
{
Assembly tmp = Assembly.LoadFile(file);
Type[] types = tmp.GetTypes();
// 遍历实例,获得实现接口的类
foreach (Type t in types)
{
if (t.GetInterface("IPlugin") != null)
{
IPlugin plugin = (IPlugin)tmp.CreateInstance(t.FullName);
m_PlugList.Add(plugin);
}
}
}
catch(Exception)
{
return 0;
}
}
return m_PlugList.Count;
}
}
|
上述的管理类能够加载DLL后缀的插件,并且将其添加到列表中来。
调用的时候,我们直接这样调用即可。
1
|
PlugManager.m_PlugList[0].Func1(1,1);
|