[转]NopCommerce MVC 插件机制分析

本文转自:http://www.cnblogs.com/haoxinyue/archive/2013/06/06/3105541.html

基本原理

插件化的应用程序一般都是先定义插件接口,然后把插件编译的dll放到固定的目录中,应用程序主程序通过加载那些实现了插件接口的dll来实现插件的使用。

NopCommerce也是这样,但作为MVC Web应用程序会有一些不一样,首先是不同信任级别(Full Trust,Medium Trust)的时候加载dll的策略会有不一样,另外就是怎样显示插件中的View的问题。

放插件的文件夹

NopCommerce的插件放在网站主目录的Plugins目录下,Plugins下面有很多文件夹,一个插件类库就是一个文件夹。

在插件类库中修改编译输出的地址为网站主目录的Plugins文件夹,这样插件生成的dll就能自动在目标文件夹下面。如下图:

另一个文件夹是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(InstalledPluginsFilePath = "~/App_Data/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里面的属性。

定义插件中的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相关插件的部分代码摘取了出来,可以从这里下载。

时间: 2024-08-29 11:03:04

[转]NopCommerce MVC 插件机制分析的相关文章

ASP.NET MVC 插件化机制

概述 nopCommerce的插件机制的核心是使用BuildManager.AddReferencedAssembly将使用Assembly.Load加载的插件程序集添加到应用程序域的引用中.具体实现可以参考nopCommerce解决方案中Nop.Core项目的Plugins目录下的相关文件.其中PluginManager.cs文件是核心文件,包含了处理插件化的核心代码.nopCommerce的注释中感谢了其参考的Umbraco项目,并给出了主要参考文章的链接. 我们直接从nopCommerce

MyBatis 源码分析 - 插件机制

1.简介 一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展.这样的好处是显而易见的,一是增加了框架的灵活性.二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作.以 MyBatis 为例,我们可基于 MyBatis 插件机制实现分页.分表,监控等功能.由于插件和业务无关,业务也无法感知插件的存在.因此可以无感植入插件,在无形中增强功能. 开发 MyBatis 插件需要对 MyBatis 比较深了解才行,一般来说最好能够掌握 MyBatis 的源码,门槛相对较高.本篇

ffmpeg转码MPEG2-TS的音视频同步机制分析

http://blog.chinaunix.net/uid-26000296-id-3483782.html 一.FFmpeg忽略了adaptation_field()数据FFmpeg忽略了包含PCR值的adaptation_filed数据; 代码(libavformat/mpegts.c)分析如下: /* 解析TS包 */int handle_packet(MpegTSContext *ts, const uint8_t *packet){  ...   pid = AV_RB16(packe

php实现网站插件机制的方法

php实现网站插件机制的方法 这些天想作一个在网站中实现插件的功能,谷歌了一下,发现一篇文章感觉对我帮助很大,帖出来和大家分享,废话不多说,直接帖出代码供大家分析. 首先是插件的管理类的实现: 复制代码 代码如下: <? /** * STBLOG PluginManager Class * * 插件机制的实现核心类 * * @package STBLOG * @subpackage Libraries * @category Libraries * @author Saturn * @link

深入解读PHP插件机制原理

深入解读PHP插件机制原理 PHP插件机制是指一类特定的功能模块,主要特点有:可以随时激活删除使用,灵活性较强.大家可以在文章中获得这一机制的相关知识. AD:51CTO移动APP安全沙龙!马上要爆满,手慢没座位! 我们在这篇文章中主要向大家讲了一些PHP插件机制的实现方法.希望大家可以通过本问介绍的内容初步了解对PHP插件机制的认识. PHP函数restore()重置PHP配置环境 PHP数据缓存类必要性分析 PHP创建PPT文档范例解析 总结各种不同PHP控制语句 PHP INCLUDE语句

typecho流程原理和插件机制浅析(第二弹)

typecho流程原理和插件机制浅析(第二弹) 兜兜 393 2014年04月02日 发布 推荐 1 推荐 收藏 14 收藏,3.7k 浏览 上一次说了 Typecho 大致的流程,今天简单说一下插件机制和插件的编写方法. 还是先上index.php if ([email protected]include_once 'config.inc.php') { file_exists('./install.php') ? header('Location: install.php') : print

浅谈ecmall插件机制

插件是独立于原系统的程序模块,目的是在不修改原程序的情况下对系统进行扩展,便于修改和管理.目前web开发中大多是使用钩子形式来定义插件, 比较典型的有 wordpress, drupal系统 ecmall的插件机制: ecmall提供了3中扩展系统功能的方法. 挂件,模块,插件. 方便我们进行二次开发.下面我们就演示一下如何制作一个插件.首先在 external/plugins目录下新建一个目录,命名为hello_world,然后进入该目录,新建2个文件 main.plugin.php 和 pl

JAVA SPI机制分析

简介 SPI的全名为Service Provider Interface,主要是应用于厂商自定义组件或插件中.在java.util.ServiceLoader的文档里有比较详细的介绍.简单的总结下java SPI机制的思想:我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块.xml解析模块.jdbc模块等方案.面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码.一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码.为

QT开发(六十三)——QT事件机制分析

QT开发(六十三)--QT事件机制分析 一.事件机制 事件是由系统或者QT平台本身在不同的时刻发出的.当用户按下鼠标.敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件.一些事件在对用户操作做出响应时发出,如键盘事件等:另一些事件则是由系统自动发出,如计时器事件. 事件的出现,使得程序代码不会按照原始的线性顺序执行.线性顺序的程序设计风格不适合处理复杂的用户交互,如用户交互过程中,用户点击"打开文件"将开始执行打开文件的操作,用户点击"保存文件"将开始执