阅读:1185回复:0
[转帖]让 ASP.NET MVC 支持 HotSwap
<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> |
|
|