MVC 4 插件化架构简单实现
转ASP.NET MVC 4 插件化架构简单实现-思路篇
用过和做过插件的都会了解插件的好处,园子里也有很多和讨论,但大都只些简单的加载程序集什么的,这里主要讨论的就是使用 ASP.NET MVC 4 来实现每个插件都可以完全从主站点剥离出来,即使只是一个插件,也是一个完整的站点,同时也可以和其它插件一起组装成一个庞大的系统。
参考资料:
ASP.NET MVC 4 源码。
Orchard 源码。
MVC3PlugInDemo 源码。
ASP.NET MVC的Razor引擎:View编译原理
基于ASP.NET MVC3 Razor的模块化/插件式架构实现
基于OSGi.NET开发ASP.NET MVC 3.0插件化应用程序
http://stackoverflow.com/questions/6923572/asp-net-mvc-3-portable-area-view-doesnt-find-my-model
首先,非常感谢以上几位大牛分享的文章,由于文笔不好,对.NET 了解也不够,希望大家多多指点。
理想情况下是希望能够像Orchard那样,可以运行时修改代码,又或者可以直接把插件(包含页面、样式、图片等资源文件)编译成一个DLL来使用(但是这样的做法会对前端与美工修改不便,而且就算改一个字也要重新编译一个DLL),只是依然还没找到方法ORZ。
最终结构图如下。

当把插件的站点发布出来后,目录名为插件名,并将该目录及目录下的所有文件复制到Plugins目录下即可自动安装并运行,不需要重启程序池。

要实现这么一个架构,最初认为,只要使用 Assembly.LoadFile(name);方法来加载外部的程序集,并且使用反射创建控制器,在定义一下MVC的模板引擎的搜索路径不就可以了吗?
当具体实现之后,发现,在不使用强类型的模型绑定时,可以正常使用,但是,使用了强类型的模型绑定时,则会出现以下错误。

问题产生原因:
.NET 会把.cshtml 与相关的程序集进行编译,之后访问的是编译后的临时程序集,但是,由于没有引用进入系统中,这里编译的时候没有该程序集,就会出现错误。
那么,要解决这个问题,就需要在编译时,把需要的程序集,都一起编译了,但是,怎么样才可以实现?
直接引用并使用类库的时候,系统会自行编译到一起了,所以解决办法有两种:
1、在系统启动前的预编译时,手动把相关的程序集增加进系统中,这样就是一个实际存在于系统的程序集,在页面编译时自然会编译进去。
在google查找相关的解决方法时,发现了该方法:
BuildManager.AddReferencedAssembly(assembly);
在查MSDN有这么一段话:此方法必须在 Global.asax 文件中的 Application_Start 事件发生前调用。
也就意味着加载程序集的方法就必须要在预启动阶段就是加载了。
并且使用上面的方法,来把程序集加到系统里。
虽然这样可以正常使用了,但是,偶尔还是会有出现编译错误的异常。
在调试阶段下,只有重新生成的代码时可以正常运行,重新生成之后的代码,在点启动调试时,就会出现编译错误问题,调试发现,在这个时候,系统并没有将需要的程序集加载到系统中,有大牛了解的话希望指点下原因。
但是,在使用了Web.config 配置文件中的节点“probing”以后,把相关的程序集复制到“probing”指定的目录下,就能正常运行了。
但是, 由于上面的那段代码只可以在预启动阶段使用,所有注定了该方法有个缺点,就是每个更新插件时,都要重启或者回收一次程序池,没能正常的做到插件化的灵活性。
2、在模板(cshtml)进行编译前,把外部引用的相关的程序集增加到编译信息中,这样在对模板进行编译的同时,会把该程序集也编译进去。
在谷歌娘的帮助下,找到了该事件:
RazorBuildProvider.CodeGenerationStarted
从名字可以看出,这是在编译启动时触发的事件,具体功能不明ORZ。
可以通过该事件,把外部的程序集增加到 RazorBuildProvider 类中。
provider.AssemblyBuilder.AddAssemblyReference(plugin.Assembly);
provider 是 RazorBuildProvider 类的一个实例。
plugin.Assembly 是一个页面所使用的程序集。
只要把这段代码放到模板引擎的搜索视图的位置,即可根据需要,将增加外部的程序集。

/// <summary>
/// 给运行时编译的页面加了引用程序集。
/// </summary>
/// <param name="pluginName"></param>
private void CodeGeneration(string pluginName)
{
RazorBuildProvider.CodeGenerationStarted += (object sender, EventArgs e) =>
{
RazorBuildProvider provider = (RazorBuildProvider)sender; var plugin = PluginManager.GetPlugin(pluginName); if (plugin != null)
{
//var assemblies = AppDomain.CurrentDomain.GetAssemblies(); //foreach (var assembly in assemblies)
//{
// provider.AssemblyBuilder.AddAssemblyReference(assembly);
//} provider.AssemblyBuilder.AddAssemblyReference(plugin.Assembly);
}
};
}

我不喜欢每装一个插件,都要重启一次,所以我选择使用了第二种方法。
下一篇,将使用第二种方法来进行具体的实践并发布源码。
MVC 4 插件化架构简单实现的更多相关文章
- ASP.NET MVC 4 插件化架构简单实现-思路篇
用过和做过插件的都会了解插件的好处,园子里也有很多和讨论,但大都只些简单的加载程序集什么的,这里主要讨论的就是使用 ASP.NET MVC 4 来实现每个插件都可以完全从主站点剥离出来,即使只是一个插 ...
- ASP.NET MVC 4 插件化架构简单实现-实例篇
先回顾一下上篇决定的做法: 1.定义程序集搜索目录(临时目录). 2.将要使用的各种程序集(插件)复制到该目录. 3.加载临时目录中的程序集. 4.定义模板引擎的搜索路径. 5.在模板引擎的查找页面方 ...
- MVC 4 插件化架构简单实现实例篇
ASP.NET MVC 4 插件化架构简单实现-实例篇 先回顾一下上篇决定的做法: 1.定义程序集搜索目录(临时目录). 2.将要使用的各种程序集(插件)复制到该目录. 3.加载临时目录中的程序集 ...
- 基于.NET MVC的高性能IOC插件化架构(一)
最近闲下来,整理了下最近写的代码,先写写架构,后面再分享几个我自己写的插件 最近经过反复对比,IOC框架选择了Autofac,原因很简单,性能出众,这篇博文是我的各大IOC框架的性能测试:http:/ ...
- 基于.NET MVC的高性能IOC插件化架构
基于.NET MVC的高性能IOC插件化架构 最近闲下来,整理了下最近写的代码,先写写架构,后面再分享几个我自己写的插件 最近经过反复对比,IOC框架选择了Autofac,原因很简单,性能出众,这篇博 ...
- ASP.NET MVC5 插件化机制简单实现
一.前言 nopCommerce的插件机制的核心是使用BuildManager.AddReferencedAssembly将使用Assembly.Load加载的插件程序集添加到应用程序域的引用中.具体 ...
- 安卓架构 视频 Android 插件化架构设计
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha Android 插件化架构设计-Dream老师 自定义SDK =====
- 基于.NET MVC的高性能IOC插件化架构(二)之插件加载原理
上一篇博文简单介绍了下插件化的代码组成部分:http://www.cnblogs.com/gengzhe/p/4390932.html,源码地址:https://github.com/luohuazh ...
- ASP.NET MVC 插件化机制
概述 nopCommerce的插件机制的核心是使用BuildManager.AddReferencedAssembly将使用Assembly.Load加载的插件程序集添加到应用程序域的引用中.具 体实 ...
随机推荐
- Android - "cause failed to find target android-14" 问题
"cause failed to find target android-14" 问题 本文地址: http://blog.csdn.net/caroline_wendy Andr ...
- ArcPad 10 的安装和部署
ArcPad它被安装在一个手持装置或业内外的移动终端ArcGIS产品,那ArcPad这是Esri软件产品,哦,不是硬件. 虽然优于ArcGIS Desktop功能复杂的乐趣,是对于野外作业.数据採集等 ...
- 前端项目部署之Grunt
如果你的前端项目很小或都者项目不需要通过专门的运维同学走流水线上线部署的话,那么可以略过以下的繁文. ok,Let's go! 我们看看如何使用grunt来部署上线项目? 前端项目一般分为两种类型:T ...
- mysql 的load data infile要使用
LOAD DATA INFILE从文本文件中读出的声明以极高的速度到表. 1.基本语法 LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'fi ...
- 【设计模式】Abstract Factory模式
抽象工厂模式是工厂方法模式的进一步强化.当工厂函数仅仅须要产生一种类型的产品(全部产品都继承自同一抽象基类)时,使用工厂方法模式就可以. 可是.当用户程序须要创建多种类型的产品,而这些产品又有一定的内 ...
- 讨论IT选定的技术招聘企业几点
在实际的招聘总结的几点思考,企业需要怎么样的人才,例如,以下个人总结: 1.技术能力是不是第一次 企业的时候,你往往看第一点的人的招聘是不是技术实力.但是,你的个人言论的行为和态度.能在半个小时内把你 ...
- 让Docker功能更强大的10个开源工具
让Docker功能更强大的10个开源工具 更好的管理.Web前端程序.更深入地了解容器应用程序,Docker生态系统正在迅速发展,这还得归功于其充满活力的开源社区. 软件项目的成功常常根据其催生的生态 ...
- 分布式服务弹性框架“Hystrix”实践与源码研究(一)
文章初衷 为了应对将来在线(特别是无线端)业务量的成倍增长,后端服务的分布式化程度需要不断提高,对于服务的延迟和容错管理将面临更大挑战,公司框架和开源团队选择内部推广Netflix的Hystrix,一 ...
- java中HashSet详解
HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...
- asp.net web api2.0 ajax跨域解决方案
asp.net web api2.0 ajax跨域解决方案 Web Api的优缺点就不说了,直接说怎么跨域,我搜了一下,主要是有两种. 一,ASP.NET Web API支持JSONP,分两种 1, ...