Lind.DDD.Plugins~插(cha)件(jian)模式的集成(cheng)
對于Lind.DDD這(zhe)個敏捷框架來說,插(cha)件(jian)也是其中的一(yi)個亮點(dian),所(suo)有被認為(wei)是插(cha)件(jian)(Plugins)的模塊(kuai)都會(hui)繼承自IPlugins這(zhe)個標示接口,它在程序啟動時(shi)會(hui)找(zhao)到所(suo)有插(cha)件(jian),并通(tong)(tong)過(guo)autofac注冊(ce)到運行時(shi)中,然(ran)后在使用(yong)時(shi)通(tong)(tong)過(guo)PluginManager對象進行獲取,即所(suo)有模塊(kuai)只注冊(ce)一(yi)次,在使用(yong)時(shi)只是從容器中取出實例的過(guo)程,這(zhe)也保證的程序的性(xing)能!
Lind.DDD.Plugins設(she)計圖(tu)
一個(ge)接口,多個(ge)實現,根據具體業務,生產不同的(de)實例,生產的(de)過(guo)程前制到程序啟動時,后期的(de)使(shi)用直接從容器中獲取(qu),由于是key/value結構(gou),所有獲取(qu)的(de)時間復雜度為O(1)
PluginModel模型
將需要動(dong)態生(sheng)產,并且后期可(ke)能(neng)發生(sheng)改變的插件持久化(hua)到數據庫(ku),文件,Nosql中,程序使用時,直接從存儲介質(zhi)里讀(du)取即可(ke)
/// <summary> /// 插件模型(xing) /// Author:Lind /// 可(ke)以被持(chi)久化到(dao)數據(ju)庫里,方便(bian)松插(cha)撥 /// 根據數據庫的值,生產對應(ying)的實例 /// </summary> public class PluginModel : Entity { /// <summary> /// 模塊名稱(cheng):對插件進(jin)行分類管理 /// </summary> public string ModuleName { get; set; } /// <summary> /// 類(lei)(lei)型(xing)顯示(shi)名稱,模塊下面的類(lei)(lei)型(xing)列表,一個模塊可以有多(duo)種類(lei)(lei)型(xing) /// </summary> public string TypeName { get; set; } /// <summary> /// 類(lei)型完整路徑,命令名稱(cheng)+類(lei)名 /// </summary> public string TypeFullName { get; set; } }
PluginManager插件管理者
沒有(you)Init(),Install()這(zhe)種初始(shi)化的方(fang)法,而直(zhi)接集成到了Config屬(shu)性(xing)上,當沒有(you)初始(shi)化時(shi),直(zhi)接進行注冊注冊插件(jian),當已經被初始(shi)化后,直(zhi)接返回容(rong)器即可,這(zhe)在程序部署時(shi),變得(de)更加(jia)自動化!
/// <summary> /// 可插拔(ba)組件的管理者 /// Author:Lind /// 依賴于Autofac /// </summary> public class PluginManager { /// <summary> /// 插(cha)件(jian)容(rong)器輔助字段(duan) /// </summary> private static IContainer _container = null; /// <summary> /// 互斥(chi)鎖 /// </summary> private static object lockObj = new object(); /// <summary> /// 類的構造(zao)方法 /// </summary> static PluginManager() { lock (lockObj) { if (_container == null) { lock (lockObj) { try { Console.WriteLine("開始(shi)注冊(IPlugins)所有插件(jian)..."); var builder = new ContainerBuilder(); foreach (var item in AssemblyHelper.GetTypesByInterfaces(typeof(IPlugins))) { builder.RegisterType(item) .Named(item.FullName, item.GetInterfaces().FirstOrDefault()); } _container = builder.Build(); } catch (Exception) { throw new ArgumentException("PluginManager依賴于autofac包包..."); } } } } } /// <summary> /// 從(cong)插(cha)件容器里返回對象 /// </summary> /// <param name="serviceName"></param> /// <param name="serviceType"></param> /// <returns></returns> public static object Resolve(string serviceName, Type serviceType) { return _container.ResolveNamed(serviceName, serviceType); } /// <summary> /// 從(cong)插件(jian)容器里(li)返回對象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="serviceName"></param> /// <returns></returns> public static TService Resolve<TService>(string serviceName) { return _container.ResolveNamed<TService>(serviceName); } }
通過這個Lind.DDD.Plugins的設計,讓我們再次領略了IoC容器的魅力,當然它的基于還是接口,多態和面向對象的基本性質,所以,學好基礎才是重中之重!
感謝各位的閱讀,非常各位多多關注倉儲大叔框架