在我前面一篇博文《逃脫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)
最後,一全景類圖和序列圖作結。