NopCommerce MVC 插件機制分析


基本原理

插件話的應用程序一般都是先定義插件接口,然后把插件編譯的dll放到固定的目錄中,應用程序主程序通過加載那些實現了插件接口的dll來實現插件的使用。NopCommerce也是這樣,但作為MVC Web應用程序會有一些不一樣,首先是不同信任級別(Full Trust,Medium Trust)的時候加載dll的策略會有不一樣,另外就是怎樣顯示插件中的View的問題。

 

放插件的文件夾

NopCommerce的插件放在網站主目錄的Plugins目錄下,Plugins下面有很多文件夾,一個插件類庫就是一個文件夾。在插件類庫中修改編譯輸出的地址為網站主目錄的Plugins文件夾,這樣插件生成的dll就能自動在目標文件夾下面。如下圖:

3OOVA%B)${1)9$RXCQJVA8C

另一個文件夾是ShadowCopy文件夾,就在Plugins/bin文件夾下。關於為什么要用ShadowCopy,住這篇文章中有所敘述,NopCommerce就是參考它的實現。里面也詳細敘述了信任級別的問題。

 

網站啟動

我們先來看PluginManager.Initialize方法。通過在PluginManager類上定義如下屬性保證PluginManager的Initialize方法在網站開始的時候運行,早於Application_Start運行。

[assembly: PreApplicationStartMethod(typeof(PluginManager), "Initialize")]

在Application_Start之前運行初始化代碼主要是為了讓網站應用程序可以引用到加載的dll。

 

核心類

IPluginFinder.cs接口:獲取插件的信息接口,在ioc里的Nop.Web.Framework.DependencyRegistrar注冊此接口。系統啟動的時候會加載到內存里。

IPlugin.cs:插件的操作接口,主要有設置插件的屬性信息,安裝插件接口,卸載插件接口。

BasePlugins.cs 實現IPlugin.cs的方法。

PluginDescriptor.cs  插件的實體類,包含了插件的版本、描述,類型,文件名稱,作者,等等一系列狀態。

PluginFileParser.cs 包含對插件的實體操作方法,主要是寫入插件的描述信息。

PluginFinder.cs 加載所有的插件,並獲取它們的信息.

PluginManager.cs 插件管理的主類,看里面的注釋,它的插件機制應該是參考的Umbraco這個cms的。

 

加載插件

首先加載插件的描述。每一個插件都必須定義一個插件描述文件,用文本文件Description.txt來定義,名字也是約定的,不能是其他名字。在插件的類庫中添加Description.txt,對插件進行描述。Description中的文本字段的格式是固定的,PluginManager會把Description.txt文件轉化成PluginDescriptor類,然后存儲在內存中。Description中的DisplayOrder字段表示了這個插件的順序,以便在界面上顯示。獲取所有的插件描述文件后,它就會去InstalledPlugins.txt里面看,在InstalledPlugins.txt里面有的就是已經安裝的查件,沒有的話就是沒有安裝的。PluginDescriptor.Installed屬性描述了這個信息。

把需要加載的dll復制到Plugins/bin文件夾下,當然都是要繼承自IPlugIn接口的,通過Assembly.Load在家這個dll,再用BuildManager.AddReferencedAssembly把這個dll加載到網站這個應用程序中。要注意的是BuildManager.AddReferencedAssembly必須早網站程序的Application_PreStartInit過程中加入,也就是在Application_Start前。這是要引用的插件都被放在了Plugins/bin下,並被CLR引用了。被引用的插件的Assembly引用將被保存在PluginManager的靜態列表中ReferencedPlugins。PluginManager的Initialize方法到此結束。

 

在界面上顯示插件

舉例來說,我們在定義插件的時候會定義一種類型的插件,比如送貨方式。那么我們在定義插件的時候會繼承2個接口,一個是IPlugin接口,一個是IShippingMethod接口。在需要顯示送貨方式插件的時候通過PluginFinder.GetPlugins<T>().ToList() 方法去獲取。PluginFinder會去上一步的PluginManager.ReferencedPlugins列表里面去尋找。返回的是IShippingMethod的實例。NopCommerce有個txt文件:InstalledPlugs.txt。只有在這個里面的插件最終會加載到界面上去。可以通過NopCommerce的查件管理頁面把最終需要作用於網站的插件加入到這個文件中。

 

 

 

配置插件

NopCommerce的admin網站可以對插件進行配置。如下圖:可以配置Display Order 和 IsActive等。主要的邏輯是更新該插件的Description.txt文件和內存中的IPlugin.Descriptor里面的屬性。K7~ABQB3W06HYXQ[_VKX{ET

 

定義插件中的Controller,Action和View

稍微復雜的插件基本都包含自己要處理的界面和邏輯。所以在插件的類庫中可以定義插件的界面View和相關Controller和Action。在建立Controller和View的時候,不一定要按照規范的Controllers文件夾和Views文件夾來定義,可以定義自己的風格。

在Action中返回View的時候,要輸入View的名稱,這個名稱要包含名稱空間,例如:

return View("Nop.Plugin.Payments.CashOnDelivery.Views.PaymentCashOnDelivery.Configure", model);

因為,在編譯過后的插件dll中,作為嵌入資源的View會被編譯成名叫Nop.Plugin.Payments.CashOnDelivery.Views.PaymentCashOnDelivery.Configure.cshtml的資源文件。

NopCommerce通過一些插件的Configure界面,把一些插件的配置信息保存到數據庫中。然后在前台頁面顯示的時候再從數據庫獲取。

 

讀取嵌入的資源View

插件作為一個類庫被加載到應用程序域中。而在定義插件的View的時候,需要把cshtml文件的屬性修改成Embedded Resource。它是作為嵌入式資源放到AppDomain中去的。我們可以通過VirtualPathProvider,使 Web 應用程序可以從虛擬文件系統中檢索資源,您可以在這篇文章中找到相關知識,NopCommerce的實現和這篇文章是一樣的。在NopCommerce中的Nop.Web.Framework類庫中有個EmbeddedViews文件夾,里面包含了如果處理嵌入的View的一些類。最后需要在Global.asax進行注冊。NopCommerce的代碼如下:

//register virtual path provider for embedded views
var embeddedViewResolver = EngineContext.Current.Resolve<IEmbeddedViewResolver>();
var embeddedProvider = new EmbeddedViewVirtualPathProvider(embeddedViewResolver.GetEmbeddedViews());
HostingEnvironment.RegisterVirtualPathProvider(embeddedProvider);

 

 

 

編寫NopCommerce插件

可以參考官方文檔。其中有一條建議非常好,就是Copy原來的插件,在上面修改。

 

 

把NopCommerce相關插件的部分代碼摘取了出來,可以從這里下載。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM