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#实现插件式架构的方法

优质内容筛选与推荐>>
1、synchronized对普通同步方法和对静态方法的区别
2、XmlPullParser 解析xml文件
3、Ubuntu 12.04 make menuconfig 出现 Unable to find the ncurses libraries or the required header files.
4、实验五 编写、调试具有多个段的程序
5、2019 年百度之星·程序设计大赛 - 初赛一 C. Mindis 离散化+dijkstra


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn