本人第一篇随笔,在园子里逛了这么久,今天也记录一篇自己的劳动成果,也是给自己以后留个记录。
最近领导让我搞一下插件化,就是实现多个web工程通过配置文件进行组装。之前由于做过一个简单的算是有点经验,当时使用的不是area,后来通过翻看orchard源码有点启发,打算使用area改一下。
实现插件化,需要解决四个问题:
1、如何发现插件以及加载插件及其所依赖的dll
2、如何注册路由,正确调用插件的Controller和Action
3、如何实现ViewEngine,正确的发现View
4、页面中的Url如何自动生成
以下下我们带着这四个问题依次分析解决:
1、如何发现插件以及加载插件及其所依赖的dll
该问题我完全使用了Nop插件的实现方式,为每个工程定义一个Plugin.txt配置文件,运行时通过注册[assembly: PreApplicationStartMethod(typeof(PluginManager), "Initialize")]这个方法,在Application_Start()之前发现和加载插件。PluginManager负责管理加载插件,通过解析Plugin.txt,识别插件的dll和它所依赖的dll。通过Assembly.Load()方法加载dll并使用BuildManager.AddReferencedAssembly(shadowCopiedAssembly)为web项目动态添加引用。由于web项目存在不同的信任级别,在FullTrust级别可以将这些dll直接拷贝到AppDomain.CurrentDomain.DynamicDirectory文件夹下面。但是在其他信任级别下无法访问该目录,Nop通过复制到一个临时目录并在web.config中修改 <probingprivatePath="Plugins/bin/" />的值来让iis自动探索该目录。
代码如下:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace Framework.Core.Plugins { public class Plugin { /// <summary> /// 插件名称,唯一标识 /// </summary> public string PluginName { get; set; } /// <summary> /// 插件显示名称 /// </summary> public virtual string PluginFriendlyName { get; set; } /// <summary> /// 插件主文件(DLL)名称 /// </summary> public string PluginFileName { get; set; } /// <summary> /// 插件控制器命名空间 /// </summary> public string ControllerNamespace { get; set; } /// <summary> /// 插件主文件文件信息 /// </summary> public virtual FileInfo PluginFileInfo { get; internal set; } /// <summary> /// 插件程序集 /// </summary> public virtual Assembly ReferencedAssembly { get; internal set; } /// <summary> /// 描述 /// </summary> public virtual string Description { get; set; } /// <summary> /// 显示顺序 /// </summary> public virtual int DisplayOrder { get; set; } /// <summary> /// 是否已安装 /// </summary> public virtual bool Installed { get; set; } } }