一.前言
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”作为插件根目录。
约定”~/Plugins/App_Data”作为中等信任级别下的运行时目录。
插件在运行时加载的是插件程序集在运行时目录的副本,不直接加载插件而是加载运行时目录中的副本的原因是避免插件升级或删除时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、图片、样式等也需要拷贝的
自动拷贝:
右键项目-->属性-->生成事件 在后期生成事件命令行填写如下命令:
注意:如果项目无任何改动,“生成”是不会编译的,所以当运行生成后事件选中“生成更新项目输出时”,不会被执行,但“重新生成”会无条件的输出,并触发事件