cl991036
管理员
管理员
  • 注册日期2003-07-25
  • 发帖数5913
  • QQ14265545
  • 铜币29658枚
  • 威望213点
  • 贡献值0点
  • 银元0个
  • GIS帝国居民
  • GIS帝国铁杆
阅读:1127回复:0

[转帖]让 ASP.NET MVC 支持 HotSwap

楼主#
更多 发布于:2007-12-14 23:22
<P>让 ASP.NET MVC 支持 HotSwap</P>
<P>下载这次的例子代码 [ <a href="http://www.cnblogs.com/Files/Lostinet/Asp35Website1.zip" target="_blank" >http://www.cnblogs.com/Files/Lostinet/Asp35Website1.zip</A> ]</P>

<P>在HowToStart那帖中,我提到了ASP.NET MVC的问题 :<BR>如果修改一次Controller的代码,就导致ASP.NET重启一次 , 那么会不会很麻烦?</P>
<P>有时候一个项目大一点, ASP.NET启动一次需要几十秒, 那样的等待真的很浪费时间.</P>
<P>与思归的交谈中, 他提到了HotSwap的概念. "热插拔" - 编写代码后不需要重新编译或重启ASP.NET.</P>
<P><BR>怎样实现这个功能呢? 现在MVC的文档很少. 只能通过Reflector去找答案了.</P>
<P>一个Request,从Url, 一直到了具体的 Controller , 经过了那些步骤呢?</P>
<P>下面列出了这个步骤的详细:<BR>1. Url<BR>2. RouteTable<BR>3. MvcRouteHandler<BR>4. MvcHandler<BR>5. ControllerBuilder<BR>6. ControllerFactory<BR>7. Controller</P>
<P>这个过程中, MvcRouteHandler 是连接 RouteTable 和 MvcHandler 的桥梁.</P>
<P>MvcHandler则根据传递过来的信息, 根据某种规则, 从所有的Assembly中找到对应的Controller类</P>
<P>然后把类型信息传递给 ControllerBuilder/ControllerFactory , 用于指定一个更具体的Controller.<BR>(类似RuntimeEntity那篇文章说的子类化模式..)</P>
<P>看来, 需要对MvcHandler下手了. 而 MvcRouteHandler 则就是 MvcHandler 的 Factory. </P>
<P>所以同时也要编写MvcRouteHandler的实现 :<BR>public class HotSwapMvcRouteHandler : System.Web.Mvc.MvcRouteHandler<BR>{<BR>    protected override IHttpHandler GetHttpHandler(System.Web.Mvc.RequestContext requestContext)<BR>    {<BR>        HotSwapMvcHandler handler = new HotSwapMvcHandler();<BR>        handler.RequestContext = requestContext;<BR>        return handler;<BR>    }<BR>}<BR>public class HotSwapMvcHandler : System.Web.Mvc.MvcHandler<BR>{<BR>    protected override Type GetControllerType(string controller)<BR>    {<BR>        string name = controller + "Controller";<BR>        string file = "~/Controllers/" + name + ".cs";<BR>        if (!System.IO.File.Exists(HttpContext.Current.Server.MapPath(file)))<BR>            return base.GetControllerType(controller);<BR>        System.Reflection.Assembly assembly = System.Web.Compilation.BuildManager.GetCompiledAssembly(file);<BR>        return assembly.GetType(name, true, true);<BR>    }<BR>}</P>
<P>上面2个类, 写在App_Code里就OK了, 然后, 需要修改一下 RouteTable 的写法:<BR>RouteTable.Routes.Add(new Route<BR>{<BR>    Url = "[controller]/[action]/[id]",<BR>    Defaults = new { action = "Index", id = "" },<BR>    RouteHandler = typeof(HotSwapMvcRouteHandler)<BR>});</P>
<P>注意一下 , RouteHandler由MvcRouteHandler替换成 HotSwapMvcRouteHandler 了.<BR>这样HotSwapMvcRouteHandler的代码就能够被执行, 返回HotSwapMvcHandler</P>
<P>HotSwapMvcHandler 这里得到了一个 controller 的参数, 就是它了.<BR>我们要做的事情,就是根据它 , 找到我们想要的 Controller </P>
<P>上面的GetControllerType的具体实现也实在太简单了.<BR>如果存在 ~/Controllers/XxxControler.cs<BR>就编译它, 然后直接返回 XxxController 类型.<BR>否则就按传统的方式去寻找对应的类.</P>
<P>----</P>
<P>OK , 就这样2步, 就实现了在 ~/Controllers/ 中存放Controller代码的目的了.<BR>重温一下这2步:<BR>1. App_Code中增加 HotSwapMvcRouteHandler , HotSwapMvcHandler<BR>2. Global.asax中修改RouteTable的定义</P>
<P><BR>然后,就可以在 ~/Controllers/ 下增加 TestController.cs , 内容是<BR>public class TestController : Controller<BR>{<BR>    [ControllerAction]<BR>    public void Index()<BR>    {<BR>        ViewData["typename"] = this.GetType().AssemblyQualifiedName;<BR>        ViewData["version"] = "version5";<BR>        RenderView("index");<BR>    }<BR>}</P>
<P>然后创建对应的 ~/Views/Test/index.aspx 把东西显示出来:<BR>index.aspx<BR><hr /><BR><%=ViewData["version"] %><BR><hr /><BR><%=ViewData["typename"] %><BR><hr /><BR><%=Application["mystr"] = "1" + Application["mystr"]%></P>
<P>显示:<BR>version5 <BR>--------------------------------------------------------------------------------<BR>TestController, App_Web_testcontroller.cs.39ee6e8a.c0bebgfm, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null <BR>--------------------------------------------------------------------------------<BR>111</P>
<P>不断地刷新它,  Application["mystr"]就会越来越长.</P>
<P>然后去修改 TestController.cs 把. 把ViewData["version"] = "version123";<BR>那么就会立刻生效, 显示version123,而Application["mystr"]没有重置, 证明ASP.NET并没有重启.</P>
<P><BR>想提高开发的方便性的朋友 , 不妨试试上面的代码.</P>
喜欢0 评分0
没钱又丑,农村户口。头可断,发型一定不能乱。 邮箱:gisempire@qq.com
游客

返回顶部