發(fā)文章
發(fā)文工具
撰寫
網(wǎng)文摘手
文檔
視頻
思維導(dǎo)圖
隨筆
相冊(cè)
原創(chuàng)同步助手
其他工具
圖片轉(zhuǎn)文字
文件清理
AI助手
留言交流
涉及內(nèi)容:
PRRT1: 反射實(shí)現(xiàn)
插件系統(tǒng)的基本目的是實(shí)現(xiàn)宿主與組件的隔離,,核心是作為接駁約定的接口,宿主使用類型發(fā)現(xiàn)及掛載插件,,以下是反射實(shí)現(xiàn)。
創(chuàng)建類庫項(xiàng)目Plugin,,添加接口IPlugin:
public interface IPlugin { String DoStuff(); }
創(chuàng)建控制臺(tái)程序HostApp,,添加對(duì)Plugin項(xiàng)目的引用,Main方法代碼:
class Program { static void Main(string[] args) { IEnumerable<Type> pluginTypes = GetPluginTypes(); foreach (Type pluginType in pluginTypes) { IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType); Console.WriteLine(plugin.DoStuff()); } } private static IEnumerable<Type> GetPluginTypes() { String root = AppDomain.CurrentDomain.BaseDirectory; String[] files = Directory.GetFiles(root, "*.dll", SearchOption.TopDirectoryOnly); foreach (String file in files) { Type[] types = Assembly.LoadFrom(file).GetTypes(); foreach (Type type in types) { if (type.IsClass && typeof(IPlugin).IsAssignableFrom(type)) { yield return type; } } } } }
創(chuàng)建類庫項(xiàng)目MyPlugin1,,添加對(duì)Plugin項(xiàng)目的引用,,添加Plugin1類并實(shí)現(xiàn)IPlugin:
public class Plugin1: IPlugin { public String DoStuff() { return "MyPlugin1 Plugin1.DoStuff"; } }
修改該項(xiàng)目的屬性,在“生成”選項(xiàng)卡中找到輸出,,將“輸出路徑”指向HostApp下的bin\Debug文件夾,,運(yùn)行。
宿主使用無參的IPlugin子類完成組件調(diào)用,。代碼邏輯并不復(fù)雜但我們還有更優(yōu)雅的解決方式即MEF框架,,這里拿MEF的完成所需功能,組件生命周期等內(nèi)容并不深入討論,,如有需求請(qǐng)自行MSDN,。
PRRT2: MEF實(shí)現(xiàn)
MEF框架以Import、Export特性為功能入口,,修改MyPlugin項(xiàng)目,,引用System.ComponentModel.Composition,,為MyPlugin添加Export特性:
[Export(typeof(IPlugin))] public class Plugin1: IPlugin { public String DoStuff() { return "MyPlugin1 Plugin1.DoStuff"; } }
注意Export明確指定導(dǎo)出類型為IPlugin,在Plugin項(xiàng)目中添加類PluginProvider,,引用System.ComponentModel.Composition和System.ComponentModel.Composition.Hosting,,添加IEnumerable<Lazy<IPlugin>>類型只讀屬性并標(biāo)注ImportMany特性:
public class PluginProvider { [ImportMany] public IEnumerable<Lazy<IPlugin>> Plugins { get; private set; } public PluginProvider() { AggregateCatalog catalog = new AggregateCatalog(); catalog.Catalogs.Add(new DirectoryCatalog(".")); CompositionContainer container = new CompositionContainer(catalog); container.ComposeParts(this); } }
抽象基類ComposablePartCatalog表示組件目錄,子類DirectoryCatalog使用指定目錄進(jìn)行搜索,。PluginProvider使用了當(dāng)前程序運(yùn)行目錄作為dll路徑,。同時(shí)導(dǎo)入點(diǎn)所在字段或?qū)傩钥梢允荌Enumerable<T>、IEnumerable<Lazy<T>>,、IEnumerable<Lazy<T, TMetadata>>等,,延遲綁定能相對(duì)降低內(nèi)存開銷,這里使用了第2種,,接著修改Main方法:
class Program { static void Main(string[] args) { PluginProvider pluginProvider = new PluginProvider(); foreach (Lazy<IPlugin> plugin in pluginProvider.Plugins) { Console.WriteLine(plugin.Value.DoStuff()); } } }
運(yùn)行得到同樣的結(jié)果,,代碼更加優(yōu)雅;根據(jù)需求,,修改PluginProvider的導(dǎo)入邏輯及使用泛型版本,,將得到更多的靈活性。代碼文件
來自: 昵稱10504424 > 《工作》
0條評(píng)論
發(fā)表
請(qǐng)遵守用戶 評(píng)論公約
也來學(xué)學(xué)插件式開發(fā)續(xù)-利用MEF
也來學(xué)學(xué)插件式開發(fā)續(xù)-利用MEF.MEF主要是通過Import與Export特性來定義導(dǎo)入與導(dǎo)出部件,。MEF程序設(shè)計(jì)指南一:在應(yīng)用程序中宿主MEF這篇文...
也來學(xué)學(xué)插件式開發(fā)
public interface Iplugin { //設(shè)置加載的主窗體 Form MainForm { get; } //插件顯示圖片 Image ModulePicture { get; } } 3 定義加載插...
C# 入門(14) 枚舉器(enumerator)和迭代器(iterator)
C# 入門(14) 枚舉器(enumerator)和迭代器(iterator)C#的枚舉器和迭代器,。枚舉器一般用來foreach的,而迭代器在Unity中常用來當(dāng)協(xié)...
PHP反射介紹及利用反射實(shí)現(xiàn)插件功能
php //定義一個(gè)自定義類 classMyTestClass{ public function testFunc($para0=''defaultValue0''){ } } //接下來反射它 foreach(get_declared_classes() as $class){ ...
C#實(shí)現(xiàn)插件式開發(fā)的一個(gè)Demo分享
using System.public static List<Iplugin> plugins = new List<Iplugin>();foreach (object attb in attbs) ...
JFinal源碼分析
= null) { for (IPlugin plugin : pluginList) { try { boolean success = plugin.start();success) { String message = "Plugin start error: "+ plugin.getClass().getName();看到了吧,,這...
Article: A simple plug-in architecture patter...
Article: A simple plug-in architecture patter...Ideally, you don''t want the application to even need to restarted -wha...
靈活正確的實(shí)現(xiàn).NET插件機(jī)制
/**////<summary>///動(dòng)態(tài)裝載并創(chuàng)建類型,該類型擁有指定接口///</summary>///<paramname="className">類型名稱</param>///<paramname="interfaceName"...
DDD領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)初探(2):倉儲(chǔ)Repository(上)
2,、站在架構(gòu)的層面,,倉儲(chǔ)解耦了領(lǐng)域?qū)雍蚈RM之間的聯(lián)系,這一點(diǎn)也就是很多人設(shè)計(jì)倉儲(chǔ)模式的原因,,比如我們要更換ORM框架,,我們只需要改變...
微信掃碼,,在手機(jī)上查看選中內(nèi)容