在我前面一篇博文《逃脱Asp.Net MVC框架的枷锁,使用Razor视图引擎》发表以后,不少人关心,脱离了以后怎么办?那么这能够说是它的续篇了。
同时,这也是eLiteWeb开源软件的一部分。 html
咱们经常提到的MVC中做为Controller的C。其实有两项任务,一个是处理Http请求,另外一个是对请求中的用户数据进行的处理。前者,有:安全认证,Url映射等。Front Controller 模式就是把这个C进一步分离。两个责任两个类(单一责任原则)。所以,这里给个人MVC模式,赋予新的内涵C => Command,以诠释两个模式的融合。 web
这是一个Adapter目的就是为了把ASP.Net环境转化为我自定义的Web抽象。 安全
首先就是BasicHttphandler自己实现了IHttpHandler,并在Web.config中设置为默认的系统HttpHandler,把控制权拿了过来,个人世界我作主。 架构
其次,把HttpContext转换为自定义的WebRequest,而后传递给Front Controller做进一步的处理处理。 框架
public class BasicHttpHandler:IHttpHandler { public class BasicHttpHandler:IHttpHandler { private FrontController front_controller; private WebRequestAdapter web_request_adapter; public BasicHttpHandler(WebRequestAdapter webRequestAdapter, FrontController frontController) { web_request_adapter = webRequestAdapter; front_controller = frontController; } public BasicHttpHandler() : this(Container.get_a<WebRequestAdapter>(),Container.get_a<FrontController>()) {} public void ProcessRequest(HttpContext context) { front_controller.process(web_request_adapter.create_from(context)); } public bool IsReusable { get {return true; } } }
它的实现也很简单,就是经过命令解析器CommandResolver,找到可执行的命令,传入WebRequest进行处理。 性能
[RegisterInContainer(LifeCycle.single_call)] public class FrontControllerImpl : FrontControllers.FrontController { private CommandResolver command_resolver; public FrontControllerImpl(CommandResolver commandResolver) { command_resolver = commandResolver; } public void process(WebRequest request) { command_resolver.get_command_to_process(request).process(request); } }
从流程上,到这里整个处理已经完成;剩下的能够看做是你本身功能的扩展。 测试
如下能够看做是个人一个具体简单实现。 this
前面提到的命令解析器我就是简单用到一个Command集合(IEnumerable<Command>),而寻找执行命令这一逻辑,是经过Command自身的方法can_process(WebRequest)的调用,从而巧妙的把责任分布到每一个具体Command自身去了。这就是集中规则,分散责任。其实,依赖注入的实现中,声明式注入(RegisterInContainerAttribute)也是相似的场景。 spa
[RegisterInContainer(LifeCycle.single_call)] public class CommandResolverImpl : CommandResolver { private IEnumerable<Command> available_commands; public CommandResolverImpl(IEnumerable<Command> availableCommands) { available_commands = availableCommands; } public Command get_command_to_process(WebRequest request) { return available_commands.First(x => x.can_process(request)); } }
仔细看看Command,这一接口又分解为两个粒度更小的接口:DiscreteCommand和过滤器Command。 .net
public interface Command : DiscreteCommand, CommandFilter { } public interface DiscreteCommand { void process(WebRequest request); } public interface CommandFilter { bool can_process(WebRequest request); }
从它们各自带的方法能够清晰的看到它们的角色分工,前者是具体处理用户数据,以后的全部具体命令处理类,如Index, Home都要实现这个接口,一个方法,从而其间简洁与单纯性已经是作到了极致;后者就是命令过滤,承担选择可执行命令的责任,Url的路由映射就实现这个接口,我这里只简单实现了用正则映射(过滤)器 RegularExpressFilter。
public class RegularExpressFilter:CommandFilter { private readonly Regex regex; public RegularExpressFilter(string match) { regex = new Regex(match); } public bool can_process(WebRequest request) { return regex.IsMatch(request.Input.RequestPath); } }
视图的这一部分,就到跳到每个具体的命令类中了,如 Index类中,经过调用WebRequest.Output.Display(View, Model),后台把调用传递到ViewEngin的一个实现类。须要知道更详细,能够到参考前文《代码整洁之道------Razor Compiler的重构》
便用示例
当要为你的Web程序建立一个页面时,只有三步:
第一步:建立一个类实现DiscreteCommand接口,并注册到Container中。在process(WebRequest)完成你须要的功能,我这只是显示一些文本,做为演示。
[RegisterInContainer(LifeCycle.singleton)] public class Index:DiscreteCommand { public void process(WebRequest request) { request.Output.Display(new View("Index"), @" <h3>卓越之行</h3> <p>宏卓科技公司专一于最新软件开发技术、开发流程和业务服务。让全部这些技术为了一个目标---您的业务服务. </p> <ul> <li> 使用行为/测试驱动方式追溯需求,驱动开发,不丢需求 </li> <li> 利用敏捷流程提升用户体验,下降风险 </li> <li> 使用良好的架构提升系统的扩展性和维护性,同时下降开发的可变成本 </li> <li> 利用对业务流程的深刻了解,开发适用软件,提供业务服务,使服务与软件无缝结合、同步发展。</li> <ul> <p> 终极目标:动成长软件,让咱们的系统与你公司的业务一块儿成长。 </p> " ); }
第二步:在映射注册类RoutesRegistration中,填加一条映射记录.。由于我不已经用命令工厂类封装了正则过滤器,因此代码看起来简单而易读一些。
public class RoutesRegistration:StartupCommand { private Registration registration; public RoutesRegistration(Registration registration) { this.registration = registration; } public void run() { var routes = Container.Current.get_a<RoutingTable>(); var factory = new CommandFactory(); routes.add(factory.match<Home>("Home.do")); routes.add(factory.match<Index>("Index.do")); } }
第三步:建立Razor页面
@inherits Skight.eLiteWeb.Presentation.Web.ViewEngins.TemplateBase<string> @{ Layout = "_Layout.cshtml"; } <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Index 页面</title> </head> <body> <h2>宏卓科技 与你公司的业务一块儿成长!</h2> <img src="/Theme/Index_pepole.jpg" style="float: left; margin-right: 50px;" /> @Model </body> </html>
总结:是的,这里的具体功能很简单,可是,相信你也看到了其强大的扩展性,如Url映射的扩展和Command扩展。与Asp.Net不一样,我这里一个Web请求是用一个类来处,而不是一个方法,这样,继承、重用和扩展都很方便。
最后一个优点:全部的处理类都是自定义的轻型类,继承层次较少,对外部的依赖为0,这个于性能是大有裨益的。
这也是把轻型做为框架名称的含义:对外依赖的轻型,性能上的轻型。
(本文版权属于© 2012 - 2013 予沁安 | 转载请注明做者和出处WangHaoBlog.com)
最后,一全景类图和序列图作结。