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

2023-05-16

用过和做过插件的都会了解插件的好处,园子里也有很多和讨论,但大都只些简单的加载程序集什么的,这里主要讨论的就是使用 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 变量来确认是否已增加过。  
<span style="white-space:pre">	</span>/// <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);
                }
            };
        }
我不喜欢每装一个插件,都要重启一次,所以我选择使用了第二种方法。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐

  • MySQL DROP TABLE操作以及 DROP 大表时的注意事项

    语法 xff1a 删表 sql view plain copy DROP TABLE Syntax DROP TEMPORARY TABLE IF EXISTS tbl name tbl name RESTRICT CASCADE 可一次删
  • python日期操作类

    coding utf 8 39 39 39 获取当前日期前后N天或N月的日期 39 39 39 from time import strftime localtime from datetime import timedelta date
  • ROS运行调用摄像头无法显示的解决办法

    报错 xff1a Unable to open camera calibration file home hri ros camera info head camera yaml 参考 xff1a https github com ros
  • [VC] 冒号(:)与C/C++

    这篇文章将总结C C 43 43 中的冒号的用法 1 位域定义 是C 43 43 里的 作用域分解运算符 比如声明了一个类A xff0c 类A里声明了一个成员函数voidf xff0c 但没有在类的声明里给出f的定义 xff0c 那么在类外
  • TX2入门(1)——开箱上电

    因为实验室有需求 导师购入了一块Jetson TX2开发板 下面就记录一下板子在我手机的应用过程 xff0c 方便以后查找 xff0c 如果也能给大家一些帮助就更好啦 欢迎转载 1 已经提前按照网上各种大神的意见采购好了电源线 HDMI转V
  • TX2入门(3)——ubuntu(包含tx2端)常用命令(持续补充中……)

    emmm xff0c 刷机完成 xff0c 突然发现还有一些常用指令需要整理一下 xff0c 以后查找起来方便 所以 xff0c tensorflow放到下一篇吧 一 系统架构类型 1 查看系统架构 uname a 2 显示操作系统架构类型
  • 使用 sphinx 制作简洁而又美观的文档

    Sphinx 是一种工具 xff0c 它允许开发人员以纯文本格式编写文档 xff0c 以便采用满足不同需求的格式轻松生成输出 这在使用 Version Control System 追踪变更时非常有用 纯文本文档对不同系统之间的协作者也非常
  • 关于C语言的空格符和字符串结束符

    空格 39 39 和结束符 39 0 39 是不一样的 xff0c 但是如果用scanf函数 s的格式输入 xff0c 遇到空格符就会当成结束符
  • 查看Jetson系列产品JetPack的版本信息

    想查看 JetPack 的版本信息 xff0c 网上搜了一下都是要查看 etc nv tegra release 也没说该怎么看和什么意思 图片链接 https www jianshu com p 7f2d8a563ded 查了一下 xff
  • docker run 参数详解

    命令格式 xff1a docker run OPTIONS IMAGE COMMAND ARG Usage Run a command in a new container 中文意思为 xff1a 通过run命令创建一个新的容器 xff08
  • Docker安装Minio

    寻找Minio镜像 Docker Hub 查找官方镜像 下载Minio镜像 下载最新版Minio镜像 span class token function docker span pull minio minio 等同于 span class
  • Docker安装Nginx

    寻找Nginx镜像 Docker Hub 查找官方镜像 下载Nginx镜像 下载最新版Nginx镜像 span class token function docker span pull nginx 等同于 span class token
  • Docker安装pgAdmin4

    寻找Redis镜像 Docker Hub 查找官方镜像 下载Redis镜像 下载最新版pgAdmin4镜像 span class token function docker span pull dpage pgadmin4 等同于 span
  • SQLServer跨库查询--分布式查询 用openrowset连接远程SQL或插入数据

    如果只是临时访问 可以直接用openrowset 查询示例 select from openrowset SQLOLEDB sql服务器名 用户名 密码 数据库名 dbo 表名 导入示例 select into 表 from openrow
  • ubuntu20 编译dpdk错误 -Werror=address-of-packed-member

    0x0 在ubuntu20上编译dpdk 18 11报错 xff0c gcc 版本为9 3 0 xff0c 报错如下 xff1a error converting a packed const struct ether addr point
  • Docker安装EMQX

    寻找EMQX镜像 Docker Hub 查找官方镜像 下载EMQX镜像 下载最新版EMQX镜像 span class token function docker span pull emqx emqx 等同于 span class toke
  • Aspose.Cells中文版文档

    Aspose Cells相应操作 1 上传 1 1 Workbook Workbook workBook 61 new Workbook 属性 名称 值类型 说明 Colors Color 获取或设置Excel颜色 ConvertNumer
  • expdp/impdp 详细参数解释

    数据泵导出实用程序提供了一种用于在 Oracle 数据库之间传输 数据对象的机制 该实用程序可以使用以下命令进行调用 示例 expdp scott tiger DIRECTORY 61 dmpdir DUMPFILE 61 scott dm
  • MSDN,我告诉你

    VS MSSQL Windows Windows Server等下载地址均为电骡下载地址 http msdn itellyou cn
  • ASP.NET MVC 4 插件化架构简单实现-思路篇

    用过和做过插件的都会了解插件的好处 xff0c 园子里也有很多和讨论 xff0c 但大都只些简单的加载程序集什么的 xff0c 这里主要讨论的就是使用 ASP NET MVC 4 来实现每个插件都可以完全从主站点剥离出来 xff0c 即使只