一.前言
nopCommerce的插件機制的核心是使用BuildManager.AddReferencedAssembly將使用Assembly.Load加載的插件程序集添加到應用程序域的引用中。具體實現可以參考nopCommerce解決方案中Nop.Core項目的Plugins目錄下的相關文件。其中PluginManager.cs文件是核心文件,包含了處理插件化的核心代碼。
我們直接從nopCommerce3.5的實現中抽取必要的實現代碼,制作一個簡易版的插件系統Demo用於演示ASP.NET MVC的插件化,核心只包含一個標記接口IPlugin,一個管理類PluginManager包含2個必要方法Initialize和ReStart。
二.新建主Web項目
主項目新建一個MVC項目,根目錄和App_Data下新建一個plugins文件夾,
約定”~/Plugins”作為插件根目錄。
約定”~/App_Data/Plugins”作為中等信任級別下的運行時目錄。
插件在運行時加載的是插件程序集在運行時目錄的副本,不直接加載插件而是加載運行時目錄中的副本的原因是避免插件升級或刪除時dll文件被鎖定。
用Neget引用:
三.新建插件
約定插件名稱要以”Plugin.”開頭例如Plugin.Demo
1.新建一個MVC項目Plugin.Demo
2.引用Plugin.Interfaces.dll 和Plugin..dll (項目packages里面或者通過nuget)
3.新建DemoPlugin 實現IPlugin 接口
具體代碼:
using System.Reflection; using System.Web.Mvc; using System.Web.Routing; namespace Plugin.Demo { public class DemoPlugin :IPlugin { public string Name { get { return Assembly.GetExecutingAssembly().GetName().Name.Replace("Plugin.", ""); } } public void Initialize() { var route = RouteTable.Routes.MapRoute( name: this.Name, url: this.Name+"/{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional, pluginName = this.Name } ); route.DataTokens["area"] = this.Name; } public virtual void Unload() { RouteTable.Routes.Remove(RouteTable.Routes[this.Name]); } } }
四.測試插件內容
手動拷貝:
1)把生成的bin文件夾、Views文件夾拷貝到主項目Plugins下的demo文件下
2)再把Plugin.Demo.dll拷貝到主項目App_data/plugins 下面
3)在主項目頁面寫個連接
@Html.ActionLink("Demo", "Index", "Home", new { area = "Demo" }, null)
看看能夠訪問到插件的內容了嗎?如果能訪問插件安裝成功了
注意:bin文件夾只留Plugin.Demo.dll和自己新建的類庫生成的Dll;如果有js、圖片、樣式等也需要拷貝的
自動拷貝:
右鍵項目-->屬性-->生成事件 在后期生成事件命令行填寫如下命令:
注意:如果項目無任何改動,“生成”是不會編譯的,所以當運行生成后事件選中“生成更新項目輸出時”,不會被執行,但“重新生成”會無條件的輸出,並觸發事件