用过和做过插件的都会了解插件的好处,园子里也有很多和讨论,但大都只些简单的加载程序集什么的,这里主要讨论的就是使用 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 是一个页面所使用的程序集。
只要把这段代码放到模板引擎的搜索视图的位置,即可根据需要,将增加外部的程序集,由于重复增加会出现已添加组件异常,所以,这里加了个 isLoadAssembly 变量来确认是否已增加过。
        /// <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)
{
provider.AssemblyBuilder.AddAssemblyReference(plugin.Assembly);
}
};
}

我不喜欢每装一个插件,都要重启一次,所以我选择使用了第二种方法。

下一篇,将使用第二种方法来进行具体的实践并发布源码。

ASP.NET MVC 4 插件化架构简单实现-思路篇

ASP.NET MVC 4 插件化架构简单实现-实例篇

ASP.NET MVC 4 插件化架构简单实现-思路篇的更多相关文章

  1. ASP.NET MVC 4 插件化架构简单实现-实例篇

    先回顾一下上篇决定的做法: 1.定义程序集搜索目录(临时目录). 2.将要使用的各种程序集(插件)复制到该目录. 3.加载临时目录中的程序集. 4.定义模板引擎的搜索路径. 5.在模板引擎的查找页面方 ...

  2. MVC 4 插件化架构简单实现实例篇

    ASP.NET MVC 4 插件化架构简单实现-实例篇   先回顾一下上篇决定的做法: 1.定义程序集搜索目录(临时目录). 2.将要使用的各种程序集(插件)复制到该目录. 3.加载临时目录中的程序集 ...

  3. MVC 4 插件化架构简单实现

    转ASP.NET MVC 4 插件化架构简单实现-思路篇   用过和做过插件的都会了解插件的好处,园子里也有很多和讨论,但大都只些简单的加载程序集什么的,这里主要讨论的就是使用 ASP.NET MVC ...

  4. ASP.NET MVC5 插件化机制简单实现

    一.前言 nopCommerce的插件机制的核心是使用BuildManager.AddReferencedAssembly将使用Assembly.Load加载的插件程序集添加到应用程序域的引用中.具体 ...

  5. 基于.NET MVC的高性能IOC插件化架构(一)

    最近闲下来,整理了下最近写的代码,先写写架构,后面再分享几个我自己写的插件 最近经过反复对比,IOC框架选择了Autofac,原因很简单,性能出众,这篇博文是我的各大IOC框架的性能测试:http:/ ...

  6. 基于.NET MVC的高性能IOC插件化架构

    基于.NET MVC的高性能IOC插件化架构 最近闲下来,整理了下最近写的代码,先写写架构,后面再分享几个我自己写的插件 最近经过反复对比,IOC框架选择了Autofac,原因很简单,性能出众,这篇博 ...

  7. Asp.Net MVC+BootStrap+EF6.0实现简单的用户角色权限管理

    这是本人第一次写,写的不好的地方还忘包含.写这个的主要原因是想通过这个来学习下EF的CodeFirst模式,本来也想用AngularJs来玩玩的,但是自己只会普通的绑定,对指令这些不是很熟悉,所以就基 ...

  8. Asp.Net MVC页面静态化功能实现二:用递归算法来实现

    上一篇提到采用IHttpModule来实现当用户访问网站的时候,通过重新定义Response.Filter来实现将返回给客户端的html代码保存,以便用户下一次访问是直接访问静态页面. Asp.Net ...

  9. Asp.Net MVC页面静态化功能实现一:利用IHttpModule,摒弃ResultFilter

    上一篇有提到利用IHttpModule和ResultFilter实现页面静态化功能.后来经过一些改动,将ResultFilter中要实现的功能全部转移到IHttpModule中来实现 Asp.Net ...

随机推荐

  1. iptables用法

    iptables -t nat -A PREROUTING -s 10.10.10.0/24 -i eth1 -p tcp --dport 80 -j REDIRECT --to-ports 3128 ...

  2. 快速清理Visual Studio起始页最近打开项目

    清除vs2008起始页最近打开项目 第一种:最简单的方式: 把以下内容保存为.bat批处理文件 @echo off@REG Delete HKCU\Software\Microsoft\VisualS ...

  3. ASPX页面包含inc文件、用户控件、普通html文件

    如果你是从asp程序员转过来一定不习惯.net的编程风格吧,代码和页面时分离的,asp和php里面时常是引入, 比如<!--#include File="xxxxxxx"-- ...

  4. hbase与Hadoop

    Hbase是一种低延迟的在线系统,Hadoop是优化吞吐量的离线系统.这种互补关系造就了一种强大的.灵活的数据平台,可以用来搭建水平扩展的数据应用.

  5. spring 知识梳理

    https://github.com/spring-projects/spring-framework  spring github地址

  6. Linux忘记密码的解救方法

    Linux版本 centos5.6 64bit 环境 vmware 忘记密码 解决方法1: 重启系统, 一.重启系统,在系统引导前按任意键进入菜单.如图:GRUB: 在引导装载程序菜单上,用上下方向键 ...

  7. 【PHP】配置环境变量

    使用Zend Framework的zf.bat创建项目时,出现如下提示:"php.exe"不是内部或外部命令,也不是可运行的程序或批处理文件. 解决方法: 配置php的环境变量: ...

  8. DOS下无法调出中文输入法-Solved

    From:http://www.cnblogs.com/killerlegend/p/3750542.html Author:KillerLegend Date:2014.5.24 DOS下无法打开中 ...

  9. python Django 学习笔记(五)—— Django admin自动管理界面

    1,激活管理界面 修改settings.py MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.c ...

  10. ruby on rails 实战(二)

    1,修改routes文件,让所有的action都可以使用get或者post方式访问 match "/:controller/:action" => "control ...