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拷貝進去。

spa

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;
        }
    }
}
相關文章
相關標籤/搜索