C# 实现插件功能

在平常的应用开发过程当中,插件化的软件更容易维护与扩展,插件作者只需要遵循指定的接口规范即可快速为软件添加新的功能。而在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);
Built with Hugo
主题 StackJimmy 设计