[转]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里面有的就是已经安装的查件,没有的话就是没有安装的。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 MVC 插件机制分析的更多相关文章
- ASP.NET MVC 插件化机制
概述 nopCommerce的插件机制的核心是使用BuildManager.AddReferencedAssembly将使用Assembly.Load加载的插件程序集添加到应用程序域的引用中.具 体实 ...
- ASP.NET MVC 插件化
ASP.NET MVC 插件化机制 2015-03-14 22:25 by 杨康新, 1328 阅读, 15 评论, 收藏, 编辑 概述 nopCommerce的插件机制的核心是使用BuildMana ...
- NopCommerce架构分析之四----插件机制
NopCommerce支持灵活的插件机制,所谓Web系统插件,其实也就是可以像原系统的一部分一样使用. Web系统的使用方式就是客户端发送一个请求,服务端进行解析.在asp.net MVC中对客户请求 ...
- MyBatis 源码分析 - 插件机制
1.简介 一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展.这样的好处是显而易见的,一是增加了框架的灵活性.二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作.以 My ...
- 精尽MyBatis源码分析 - 插件机制
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- 精尽Spring MVC源码分析 - 寻找遗失的 web.xml
该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...
- typecho流程原理和插件机制浅析(第二弹)
typecho流程原理和插件机制浅析(第二弹) 兜兜 393 2014年04月02日 发布 推荐 1 推荐 收藏 14 收藏,3.7k 浏览 上一次说了 Typecho 大致的流程,今天简单说一下插件 ...
- typecho流程原理和插件机制浅析(第一弹)
typecho流程原理和插件机制浅析(第一弹) 兜兜 393 2014年03月28日 发布 推荐 5 推荐 收藏 24 收藏,3.5k 浏览 虽然新版本0.9在多次跳票后终于发布了,在漫长的等待里始终 ...
- [2017-08-21]Abp系列——如何使用Abp插件机制(注册权限、菜单、路由)
本系列目录:Abp介绍和经验分享-目录 Abp的模块系统支持插件机制,可以在指定目录中放置模块程序集,然后应用程序启动时会搜索该目录,加载其中所有程序集中的模块. 如何使用这套机制进行功能插件化开发? ...
随机推荐
- 认识Android
安卓的特点开放性平等性无界性方便性硬件的丰富性 Android操作系统之中,一共将体系结构划分为四层:应用层(Application).应用框架层(Application Framework).系统运 ...
- c语言内存模型
文章一.C语言的内存分配模型 1.程序代码区:存放函数体的二进制代码. 2.全局区数据区:全局数据区划分为三个区域.全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化 ...
- sql Sever 修改表中的列名
EXEC SP_RENAME 'LeInterface.iYear','iLeYear','COLUMN' EXEC SP_RENAME 'LeInterface.imonth','iLemonth' ...
- MSSQL 生成有意义的PROC
MSSQL 生成有意义的PROC --MSSQL 用PROC 生成有意义的单号:如WP200011101 GO/****** 对象: Table [dbo].[tbl_SequenceNum] ...
- HDU_2032——杨辉三角
Problem Description 还记得中学时候学过的杨辉三角吗?具体的定义这里不再描述,你可以参考以下的图形:11 11 2 11 3 3 11 4 6 4 11 5 10 10 5 1 ...
- HDU_2011——求多项式的前n项和
Problem Description 多项式的描述如下:1 - 1/2 + 1/3 - 1/4 + 1/5 - 1/6 + ...现在请你求出该多项式的前n项的和. Input 输入数据由2行组 ...
- Android笔记(三):View一些值得注意的地方
Button android:textAllCaps="false" // Button上的英文字符不转成大写 EditText android:maxLines="2& ...
- JS瀑布流效果
本篇内容实现类似百度图片的呈现功能,瀑布流+自动加载 index13.html <!DOCTYPE html> <html> <head> <meta cha ...
- ionic学习教程地址梳理
Ionic是一个新的.可以使用HTML5构建混合移动应用的用户界面框架,它自称为是"本地与HTML5的结合".该框架提供了很多基本的移动用户界面范例,例如像列表(lists).标签 ...
- [C/C++标准库]_[0基础]_[交集和补集]
场景: 1. 计算std::vector A和 std::vector B里的同样的元素, 用于保留不删除. 2. 计算std::vector A和 std::vector B里各自的补集, 用于删除 ...