简单的c#插件框架

Posted 三小

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单的c#插件框架相关的知识,希望对你有一定的参考价值。

插件式架构,一种全新的、开放性的、高扩展性的架构体系.插件式架构设计近年来非常流行,基于插件的设计好处很多,把扩展功能从框架中剥离出来,降低了框架的复杂度,让框架更容易实现。扩展功能与框架以一种很松的方式耦合,两者在保持接口不变的情况下,可以独立变化和发布。基于插件设计并不神秘,相反它比起一团泥的设计更简单,更容易理解。下面已C# .Net简要介绍一下插件式架构的方法.

定义插件接口,将其编译成dll
namespace PluginInterface
{
      public interface IPlugin
      {
             string Show();
      }
}


编写插件,引用上面的DLL,实现上面定义的接口,也编译为DLL
//插件A
namespace PluginA
{
    public class PluginA:IPlugin
    {
        public string Show()
        {
            return "插件A";
        }
    }
}


//插件B
namespace PluginB
{
    public class PluginB : IPlugin
    {
        public string Show()
        {
            return "插件B";
        }
    }
}


新建一个控制台程序,需要引用定义插件接口的dll,生成之后,需要在exe所在的目录里建一个Plugins子文件夹,将上面生成的PluginA.dll,和PluginB.dll拷贝进去。

namespace ConsolePluginTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            List<string> pluginpath =  p.FindPlugin();

            pluginpath = p.DeleteInvalidPlungin(pluginpath);

            foreach (string filename in pluginpath)
            {
                try
                {
                    //获取文件名
                    string asmfile = filename;
                    string asmname = Path.GetFileNameWithoutExtension(asmfile);
                    if (asmname != string.Empty)
                    {
                        // 利用反射,构造DLL文件的实例
                        Assembly asm = Assembly.LoadFile(asmfile);
                        //利用反射,从程序集(DLL)中,提取类,并把此类实例化
                        Type[] t = asm.GetExportedTypes();
                        foreach (Type type in t)
                        {
                            if (type.GetInterface("IPlugin") != null)
                            {
                                IPlugin show = (IPlugin)Activator.CreateInstance(type);
                                Console.Write(show.Show());
                            }
                        }
                    }
                }
                catch(Exception ex)
                {
                    Console.Write(ex.Message);
                }
            }
        }

        //查找所有插件的路径
        private List<string> FindPlugin()
        {
            List<string> pluginpath = new List<string>();
            try
            {
                //获取程序的基目录
                string path = AppDomain.CurrentDomain.BaseDirectory;
                //合并路径,指向插件所在目录。
                path = Path.Combine(path,"Plugins");
                foreach (string filename in Directory.GetFiles(path, "*.dll"))
                {
                    pluginpath.Add(filename);
                }
            }
            catch(Exception ex)
            {
                Console.Write(ex.Message);
            }
            return pluginpath;
        }
        //载入插件,在Assembly中查找类型
        private object LoadObject(Assembly asm, string className, string interfacename
                        , object[] param)
        {
            try
            {
                //取得className的类型
                Type t =asm.GetType(className);
                if (t == null
                    || !t.IsClass
                    || !t.IsPublic
                    || t.IsAbstract
                    || t.GetInterface(interfacename) == null
                   )
                {
                    return null;
                }
                //创建对象
                Object o = Activator.CreateInstance(t,param);
                if (o == null)
                {
                    //创建失败,返回null
                    return null;
                }
                return o;
            }
            catch
            {
                return null;
            }
        }
        //移除无效的的插件,返回正确的插件路径列表,Invalid:无效的
        private List<string> DeleteInvalidPlungin(List<string> PlunginPath)
        {
            string interfacename = typeof(IPlugin).FullName;
            List<string> rightPluginPath = new List<string>();
            //遍历所有插件。
            foreach (string filename in PlunginPath)
            {
                try
                {
                    Assembly asm = Assembly.LoadFile(filename);
                    //遍历导出插件的类。
                    foreach (Type t in asm.GetExportedTypes())
                    {
                        //查找指定接口
                        Object plugin = LoadObject(asm,t.FullName,interfacename,null);
                        //如果找到,将插件路径添加到rightPluginPath列表里,并结束循环。
                        if (plugin != null)
                        {
                            rightPluginPath.Add(filename);
                            break;
                        }
                    }
                }
                catch
                {
                    throw new Exception(filename+"不是有效插件");
                }
            }
            return rightPluginPath;
        }
    }
}

以上是关于简单的c#插件框架的主要内容,如果未能解决你的问题,请参考以下文章

完全开源基于插件的开发框架(使用DEV实现Ribbon界面)

C#]插件编程框架 MAF 开发总结

VSCode插件开发全攻略代码片段设置自定义欢迎页

C# 最有用的(自定义)代码片段是啥? [关闭]

XSS:如何从 C# 中的字符串中删除 JS 片段?

此 Canon SDK C++ 代码片段的等效 C# 代码是啥?