MVC插件开发学习

本文内容基于

cjnmy36723 http://www.cnblogs.com/cjnmy36723/p/3405269.htmlBrnShop(其实他是借chao鉴nopcommerce的)

下文中会提及它们是如何解决问题,在这之前给他们取个小名

cjnmy36723               方案一

BrnShop                      方案二

 

本文不讲代码细节

什么MVC插件

目前我所理解的MVC插件是

  • 可独立运行的
  • 容易部署的
  • 容易删除的

我们所想象的插件,是只要把插件文件复制到指定位置,并修改配置就能运行的.

那么就先约定一个Plugins目录来放插件

平时访问MVC网站经过的流程大致为:

Url被路由获取-->路由匹配-->找到相关控制器-->控制器找到相关视图

开发一个插件,并让站点使用会遇到很多坑

那么就从视图,控制器,路由方面 开始解决它们.

控制器问题

如何让网站不仅能拿到网站本身的控制器类,同时能拿到插件的控制器类

那么就要了解下控制器如何被创造出来的

推荐看artech的博客

这里只说相关部分的

通常控制器是被一个控制器工厂类(DefaultControllerFactory)创建出来的

这个类实现了IControllerFactory接口

该接口有三个方法

//使用指定的请求上下文来创建指定的控制器。
IController CreateController(RequestContext requestContext, string controllerName);
//获取控制器的会话行为。
SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName);
//释放指定的控制器
void ReleaseController(IController controller);

获得控制器的关键就是
CreateController方法

只要修改这个方法,让他不仅仅能获得网站自己的控制器类,同时能获得插件的控制器类

当然我们修改的话,并不需要自己实现IControllerFactory创建自己的控制器工厂类,我们可以重写DefaultControllerFactory相关的方法

DefaultControllerFactory除了能重写IControllerFactory的三个方法外还能重写

  1. protected internal  virtual TypeGetControllerType(RequestContext  requestContext,string controllerName)

为了达到我们的目的可以重写这个方法,因为根据源码,CreateController创建实例需要Type,即会用到GetControllerType方法

最简单的处理:可以重写这个方法,让它反射程序集,创建控制器

下面介绍下两个案例是如何处理控制器的

部署程序集

显然无论哪种方法都需要加载程序集,这里需要注意的是两种方案都把程序集复制到另一个文件夹下

 

方案一

复制到 ~/App_Data/Dependencies

方案二

它略微复杂点,它尝试把插件的dll复制到运行时文件夹

临时文件夹大概在C:\Users\用户名\AppData\Local\Temp\Temporary ASP.NET Files

这里就涉及到了权限问题

BrnShop的BrnMall.Core.BMAPlugin.DeployDllFile方法中它判断应用程序的信任级别,如果是最高等级的信任级别就把插件dll复制到运行时文件夹.如果不是则复制到/plugins/bin.

之所以要复制程序集,因为使用Assembly.LoadFrom方法后,将把该程序集锁定,那么久不能移动,删除程序集了

这里我无意间在网上看到了一个解决方法.把dll以字节的形式读取到内存,再生成Assembly,这样似乎锁程序集

但我仍然有个疑惑,为什么BrnShop要尝试把程序集复制到运行时文件夹?归在一个文件夹不好吗?求解答

使用程序集

部署好程序集后,就要想办法,让网站能用到这个程序集

方案一

 

方案二

 

BrnShop并不是像上面那样运行时反射加载程序集并保存起来用

确切的说他是运行前加载程序集并添加引用

在它的BrnMall.Core.BMAPlugin.DeployDllFile 方法中,它读取插件程序集并使用BuildManager.AddReferencedAssembly添加程序集引用.

这里有个知识点:CLR是如何搜索dll的?
相关资料:http://www.cnblogs.com/Charles2008/archive/2010/07/02/Assembly_Search.html

这里我说下相关部分

CLR会按照下面的顺序搜索程序集,但提前这个程序集要被引用,只有被引用的程序集才会出现在程序集清单中,CLR搜索程序集就是靠清单上的信息

1、 在GAC(Global Assembly Cache)中搜索相应版本的DLL

2、 配置文件(web.config或app.config)中

  1. <codebaseversion=”AssemblyVersion" href=”URL of assembly” />

3、 应用程序当前目录下

4、 配置文件(web.config或app.config)

  1. <probingprivatePath=”Paths”/>

所以Brnshop不仅动态添加了引用,同时设置了<probing>节点

  1. <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <!--插件dll文件影子目录,在Medium及其以下的信任级别时使用-->
        <probing privatePath="plugins/bin/"/>
        <dependentAssembly>
          <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
          <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0"/>
        </dependentAssembly>
      </assemblyBinding>
    </runtime>

这样做后,网站就能想找自己控制器一样轻松的找到插件的控制器

存在问题,使用这种方法,如果在网站运行时添加插件,毕竟运行的情况下是不同添加引用的

视图问题

这里要了解想MVC的Razor视图是如何被编译出来的

推荐看artech的MVC视图系列文章

http://www.cnblogs.com/artech/archive/2012/09/04/razor-view-engine-01.html

这里也只说相关部分的

找视图

视图引擎RazorViewEngine的爷爷
VirtualPathProviderViewEngine(抽象类)

它内部有一些数组用于保存视图的路径

  1. public string[] AreaMasterLocationFormats{ get; set; }
    public string[] AreaPartialViewLocationFormats{ get; set; }
    public string[] AreaViewLocationFormats{ get; set; }
    public string[] FileExtensions{ get; set; }
    public string[] MasterLocationFormats{ get; set; }
    public string[] PartialViewLocationFormats{ get; set; }
    public IViewLocationCache ViewLocationCache{ get; set; }
    public string[] ViewLocationFormats{ get; set; }

显然根据名字就知道,它们是哪些视图的路径

它们在RazorViewEngine中初始化,下面给出一部分的代码

  1. public RazorViewEngine(IViewPageActivator viewPageActivator) : base(viewPageActivator)
    {
      //省略....
      base.ViewLocationFormats = new string[]
      {
        "~/Views/{1}/{0}.cshtml",
        "~/Views/{1}/{0}.vbhtml",
        "~/Views/Shared/{0}.cshtml",
        "~/Views/Shared/{0}.vbhtml"
      };
    
      //省略...
    }

上面的路径仅仅是个模板,真正的路径将在运行时候根据路由请求被修改

这部分操作被写在 VirtualPathProviderViewEngine中的

  1. public virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
    {
      ...
    }

易知,这个方法可以被重写,那么我们可以修改FindView方法和ViewLocationFormats等数组,让视图引擎能找到插件的视图

编译视图

如果你看过artech的文章,应该明白,视图(.cshtml)将在运行的时候编译成一个类保存在运行时文件夹

临时文件夹大概在

C:\Users\用户名\AppData\Local\Temp\Temporary ASP.NET Files

  那么这里就出现了一个 坑

由于是把视图文件(.cshtml)编译成一个dll,那么当这个视图是模型视图,也就是用到了自己创建的Model类时候该去哪个dll找我的Model?

通常情况下,我写的Model都跟我的MVC网站编译成一个dll

比如

我的网站将编译成一个PluginMvcWeb.dll保存在bin下,运行时也会保存在临时文件夹下.

方案一

他也设置了<probing>节点,告诉CLR去哪里搜索dll

可能有人问,这个视图类还没引用程序集,我写到这也惊得菊花一紧.然而神奇的是这视图类会自动添加引用

方案二

它是写死视图的路径(毕竟是约定大于配置的项目),同样也设置了<probing>节点

路由

方案一

每个插件加载时候都会调用一个初始化函数,在这个函数中每个插件都会注册一条路由

方案二

额.......,它似乎并没改动什么,它是约定大于配置的,主网站默认的路由配置已经能够匹配到插件的位置

未完待撸...

时间: 2024-10-13 06:27:50

MVC插件开发学习的相关文章

Eclipse插件开发 学习笔记 PDF 第一篇到第四篇 免分下载 开发基础 核心技术 高级进阶 综合实例

<<Eclipse插件开发 学习笔记>>,本书由浅入深.有重点.有针对性地介绍了Eclipse插件开发技术,全书分为4篇共24章.第一篇介绍Eclipse平台界面开发的基础知识.包含SWT控件的使用.界面布局.事件处理等内容:第二篇是插件开发核心技术,主要介绍插件开发的核心知识要点,包含行为(Action).视图(ViewPart).编辑器(Editor).透视图(Perspective)等10章的内容.第三篇主要讲述插件开发的高级内容,包含开发高级内容.富client平台技术(R

.Net MVC的学习(一)

套种间作,也挺有意思的--近来学习感悟.DRP学习的同时,折腾了点以前不曾学习但是却很多次耳闻过的东西--Asp.Net中的MVC架构模式. 一.是什么? MVC,即(Model-View-Controller,模型-视图-控制器模式),和三层类似,用于表示一种软件架构模式.在这种模式下,将系统的实现分为模型Model,视图View,控制器Controlller.其中Model:对数据库的操作和一般的业务逻辑.View:负责做出和用户交互的显示:Controller:处理Request和Resp

(asp.net MVC学习)System.Web.Mvc.HtmlHelper学习及使用

在ASP.NET MVC框架中没有了自己的控件,页面显示完全就回到了写html代码的年代.还好在asp.net mvc框架中也有自带的HtmlHelper和UrlHelper两个帮助类.另外在MvcContrib扩展项目中也有扩展一些帮助类,这样我们就不光 只能使用完整的html来编写了需要显示的页面了,就可以使用这些帮助类来完成,但最后运行时都还是要生成html代码的. 先来看看HtmlHelper能帮我们生成一些什么样的html呢.直接看效果吧. <div>          1.使用Ht

[转]ASP.NET MVC 5 学习教程:快速入门

本教程将使用Visual Studio 2013手把手教你构建一个入门的ASP.NET MVC5 Web应用程序.本教程配套的C#源码工程可通过如下网址下载:C#版本源码链接.同时,请查阅 Building the Chapter Downloads 来完成编译源码和配置数据库. 在本教程中的源码工程,您可在Visual Studio中运行MVC 5应用程序.您也可以使Web应用程序部署到一个托管服务提供商上.微软提供免费的网络托管多达10个网站,free Windows Azure trial

eclipse插件开发学习笔记

2016-09-01 17:11:50 1. 概述 1.1 SWT/JFace 是Eclipse 的基础,Eclipse 的 Workbench 就是建立在 SWT/JFace 之上的.另外,JFace 是在 SWT 之上开发的,它和 SWT 形成一个交集, 其中 SWT 提供最原始的组件,如下图所示 JFace是在SWT的基础上创建的,但JFace并不能完全覆盖SWT的功能 这两个图下面那个应该是对的,上面那个有点问题吗? 1.2 SWT是一个库,依赖于本机操作系统的库,会体现主机的GUI库特

mvc Bundling 学习记录

因为现在的项目JS引用很多,无意中看到了MVC4的Bundling,开始的时候感觉很不错,将所有的CSS,js文件压缩成一个文件处理,画面调用也很简单 于是,花了一个下午的时候研究了一下,并且通过各种情况进行测试 可是结果不尽如人意,其中有一个比较很让人抓狂的问题 经常做.NET的人都知道,UI画面会引用很多的插件,比如easyui,ext等等,而这些插件里面包含了很多图片引用,因为图片呢,就涉及到一个做WEB的常见难题:路径(当然,如果所有的CSS文件中图片路径都是使用的绝对路径或者项目绝对路

mvc Bundling 学习记录(一)

参考博客:http://www.cnblogs.com/xwgli/p/3296809.html 这里要详细记录的是对于现有MVC项目进行Bundling功能 1  如果没有System.Web.Optimization这个应用,则通过nuget搜索安装System.Web.Optimization   2  在web.config(两个)添加<add namespace="System.Web.Optimization" />这一行  3  Global.asax 里面添

MVC基础学习—理论篇

1.      简介 ?  定义?什么是MVC     MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑.MVC被独特的发展起来用于映射传统的输入.处理和输出功能在一个逻辑的图形化用户界面的结构中. ?  VC模式和我们熟悉的WebForm模式    

第一周之mvc入门学习

公司下一个项目需要用 mvc来实现 ,在前几个月自己也看过一些mvc方面的资料但也只是了解了一下并没有达到应用的水准.自己虽然有计划过业余时间来学习mvc但是个人意志不是很坚定学了一段时间也就不了了之了.这次选用mvc来做项目我还是挺高兴,毕竟现在年轻想趁着年轻多学点东西 以后的日子会好过点吧. 这一周主要是学习的原理方面的知识和一些基础应用. 个人所以理解mvc与webfrom的几点区别吧. 1.webfrom后台类与前台页面类的关系是继承关系.mvc则后台和前台完全分离并且可以返回不同的视图