最近在开发一个MVC框架,开发过程当中考虑到之后开发依托于框架的项目,为了框架的维护更新升级,代码确定要和具体的业务工程分割开来,因此须要解决业务工程挂载在框架工程的问题,MVC与传统的ASP.NET不一样,WebForm项目只须要挂在虚拟目录拷贝dll就能够访问,可是MVC不可能去引用工程项目的dll从新编译,从而产生了开发一个动态挂在MVC项目功能的想法,MVC项目挂载主要有几个问题,接下来进行详细的分析与完成解决方案html
通常动态加载dll的方法是使用Assembly.LoadFIle的方法来调用,可是会存在以下问题:git
经过 BuildManager.AddReferencedAssembly方法在MVC项目启动前,动态将外部代码添加到项目的编译体系中,须要配合PreApplicationStartMethod注解使用,示例:web
声明一个类,而后进行注解标记,指定MVC启动前方法mvc
//使用PreApplicationStartMethod注解的做用是在mvc应用启动以前执行操做 [assembly: PreApplicationStartMethod(typeof(FastExecutor.Base.Util.PluginUtil), "PreInitialize")] namespace FastExecutor.Base.Util { public class PluginUtil { public static void PreInitialize() { } } }
经过自定义的ControllerFactory重写GetControllerType方法进行识别app
在Global.asax文件中进行ControllerFactory的替换框架
ControllerTypeDic是遍历外部dll获取到的全部Controller,这里须要考虑到Controller经过RoutePrefix注解自定义Controller前缀的状况ide
解决办法是经过AppDomain对业务项目dll独立加载,更新时进行卸载ui
1)建立一个RemoteLoader一个可穿越边界的类,做为加载dll的一个包装spa
2)建立LocalLoader做为AppDomian建立与卸载的载体插件
这里须要说明的,AppDomainSetup配置文件请使用AppDomain.CurrentDomain.SetupInformation也就是使用框架的做用于配置信息,由于业务代码会引用到不少框架的dll,若是独立建立配置信息,会有找不到相关dll的错误,同时这里也须要配置web.confg文件指定额外的dll搜索目录,由于业务工程代码也会有不少层多个dll相互引用,不指定目录也会存在找不到依赖dll的错误
3)建立业务代码文件夹Plugin与临时dll文件夹PluginTemp
为何要建立临时文件夹呢,由于咱们须要在PluginTemp真正的加载dll,而后监听Plugin文件夹的文件变化,有变化时进行AppDomain卸载这个操做,将Plugin中的dll拷贝到PluginTemp文件夹中,再从新加载dll
监听Plugin文件夹:
拷贝dll:
注:这里有个问题一直没解决,就是删除文件拷贝文件的时候,AppDomain已经卸载,可是始终提示无权限错误,可是操做又是成功的,暂时还未解决,若是你们有解决方法能够一块儿交流下
加载dll:
在MVC工程中,cshtml也是须要被编译的,咱们能够经过RazorBuildProvider将外部编译的页面动态加载进去
RazorBuildProvider方法啊只是在路由层面将cshtml加入到框架中,咱们还须要将业务工程View中模块的页面挂载虚拟目录到框架中,如图所示
在启动的项目中咱们更新dll,咱们但愿达到的效果是和更新框架bin目录文件的dll同样,程序会重启,这样就会再次调用被PreApplicationStartMethod注解标注的方法,不须要在代码中作额外处理判断是首次加载仍是更新加载,同时也作不到动态的将外部dll加入到MVC编译dll体系中,也只能启动前加载,查了不少资料,从新加载项目能够经过代码控制IIS回收程序池达到效果,可是由于各类繁琐的权限配置问题而放弃,我最后的解决方法是比较歪门邪道的方法,更新web.config文件的修改日期,由于iis会监控配置文件,更新了会重启引用,你们若是有更好的简单的方法,能够评论回复我呦
博客园没找到资源上传地址,传到码云上了,放个地址:https://gitee.com/grassprogramming/FastExecutor/attach_files