愛(ai)上(shang)MVC~一個Action多套View模版的(de)設計
模塊化
這個問(wen)題(ti)是在(zai)(zai)(zai)做模(mo)(mo)塊(kuai)化(hua)設計時出(chu)現的,在(zai)(zai)(zai)Lind.DDD.Plugins模(mo)(mo)塊(kuai)里,需(xu)要(yao)對應(ying)的模(mo)(mo)塊(kuai)實體,模(mo)(mo)塊(kuai)管(guan)理者,模(mo)(mo)塊(kuai)標識接(jie)口等,開發(fa)時,如(ru)果(guo)你的功能(neng)點屬于一個模(mo)(mo)塊(kuai),需(xu)要(yao)實現IPlugins,而(er)當實現了(le)標識接(jie)口后,在(zai)(zai)(zai)應(ying)用程(cheng)序啟動時,會一次性將(jiang)所有(you)插件(jian)模(mo)(mo)塊(kuai)注冊(ce)到你的系統里,在(zai)(zai)(zai)需(xu)要(yao)使用時,只(zhi)要(yao)使用PluginManager管(guan)理者把(ba)對應(ying)的模(mo)(mo)塊(kuai)取出(chu)來即可,這個取出(chu)的過程(cheng)是沒有(you)性能(neng)損耗的,它并不是反射!
更多Lind.DDD.Plugins的相關知識,請閱讀大叔這篇文章《Lind.DDD.Plugins~插件模式的集成》
模塊化在UI層的體現
本文主要(yao)問題是在(zai)設(she)計(ji)出(chu)多(duo)個(ge)(ge)模(mo)塊(kuai)是,在(zai)UI層如(ru)何根據(ju)(ju)選中的(de)(de)模(mo)塊(kuai),渲染出(chu)不同的(de)(de)VIEW來(lai)(lai),這(zhe)個(ge)(ge)問題不是新技術(shu),只(zhi)需要(yao)使(shi)(shi)用(yong)(yong)(yong)Html.Partial這(zhe)個(ge)(ge)擴展(zhan)方法即可以(yi)實現,而大叔要(yao)說的(de)(de)是,我(wo)(wo)們(men)(men)設(she)計(ji)模(mo)塊(kuai)時,應該(gai)把所(suo)有(you)模(mo)塊(kuai)放在(zai)一(yi)個(ge)(ge)統一(yi)的(de)(de)目(mu)錄,新來(lai)(lai)的(de)(de)模(mo)塊(kuai)View只(zhi)要(yao)放到module即可,由于模(mo)塊(kuai)核(he)心內容都(dou)寫在(zai)對(dui)應的(de)(de)module中,controller/action變得(de)更加(jia)輕薄,這(zhe)時,我(wo)(wo)們(men)(men)很容易(yi)使(shi)(shi)用(yong)(yong)(yong)autofac這(zhe)些IoC工具(ju)把需要(yao)的(de)(de)模(mo)塊(kuai)對(dui)象動(dong)態生(sheng)產(chan)出(chu)來(lai)(lai),這(zhe)也(ye)是Lind.DDD.Plugins要(yao)做的(de)(de)事情,只(zhi)不過(guo),為了性能(neng)考慮(lv),我(wo)(wo)們(men)(men)在(zai)程序(xu)啟動(dong)時已經把所(suo)有(you)模(mo)塊(kuai)注(zhu)冊(ce)了,對(dui)于核(he)心業務的(de)(de)action,所(suo)有(you)模(mo)塊(kuai)共(gong)用(yong)(yong)(yong)一(yi)個(ge)(ge)即可,如(ru)列(lie)表(biao)action使(shi)(shi)用(yong)(yong)(yong)Index,添加(jia)action使(shi)(shi)用(yong)(yong)(yong)Create,而controller我(wo)(wo)們(men)(men)使(shi)(shi)用(yong)(yong)(yong)比較公用(yong)(yong)(yong)的(de)(de)名稱,如(ru)商品(pin)管理(li)Product,訂單管理(li)Order,而具(ju)體的(de)(de)手機項目(mu)product和(he)order及PC端的(de)(de)product和(he)order完全在(zai)對(dui)應的(de)(de)module里去(qu)實現(邏輯上的(de)(de)實現),而它們(men)(men)的(de)(de)action只(zhi)會路由的(de)(de)轉發,即根據(ju)(ju)項目(mu)去(qu)選擇(ze)渲染哪一(yi)個(ge)(ge)View。
WEB MVC下(xia)面Module的組成
程序啟動時(shi)注(zhu)冊Module這個特殊的(de)路由模塊(kuai),讓我(wo)們的(de)mvc程序可以(yi)找個Module下面(mian)的(de)Views,這個只對需(xu)要有(you)具體Action時(shi)用,如果你(ni)的(de)module只有(you)view,action都(dou)有(you)公用模塊(kuai)實現了(le)(le),就(jiu)不需(xu)要注(zhu)冊下面(mian)代碼了(le)(le)!
/// <summary> /// 注冊模塊 /// </summary> public class Module_routing : RazorViewEngine { public Module_routing() { //視(shi)圖位置 ViewLocationFormats = new[] { "~/Views/{1}/{0}.cshtml", "~/Views/Module/{1}/{0}.cshtml" }; //分部(bu)視圖位置 PartialViewLocationFormats = new[] { "~/Views/{1}/{0}.cshtml", "~/Views/Shared/{0}.cshtml", "~/Views/Module/Shared/{0}.cshtml", "~/Views/Module/{1}/{0}.cshtml" }; } public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) { return base.FindView(controllerContext, viewName, masterName, useCache); } public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) { return base.FindPartialView(controllerContext, partialViewName, useCache); } }
在程(cheng)序啟動(dong)時(shi),把它的實例(li)注冊進來
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); RegisterView_Custom_routing(); } protected void RegisterView_Custom_routing() { ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new Module_routing()); }
而(er)在公(gong)用的(de)action里,一般(ban)來說,會接收一個moduleName或者ModuleId這種屬性,然后生產對應的(de)模塊對象(xiang),把對象(xiang)的(de)結果傳給對應的(de)View即可。
public ActionResult Index(string module) { var model=Plugins.PluginManager.Resolve<IShop>("module").GetModel();//這(zhe)個地(di)方不(bu)是反射,只是從容(rong)器里把對應的實例取出(chu)來 return View(model); }
在主View上進行(xing)渲染(ran)對(dui)應項目的PartialView,同時(shi)把Model傳給對(dui)應的View,一般代碼(ma)如下
<ul>
<li>@Html.ActionLink("pc端(duan)", "index", new { module = "pc" })</li>
<li>@Html.ActionLink("h5端", "index", new { module = "h5" })</li>
<li>@Html.ActionLink("pad端", "index", new { module = "pad" })</li>
</ul>
@Html.Partial("~/views/module/"+Request.QueryString["module"] + "/index.cshtml",Model) <!-- 渲染對應(ying)的模塊下(xia)的頁面(mian),Model由公(gong)用action返回(hui) -->
這樣產(chan)生的(de)(de)(de)(de)(de)好處就(jiu)(jiu)是,當你添加(jia)新(xin)(xin)的(de)(de)(de)(de)(de)module時,只需要維(wei)護對應的(de)(de)(de)(de)(de)Project即可(ke)(ke),然(ran)后把主網(wang)站的(de)(de)(de)(de)(de)Views/Module文件夾(jia)更新(xin)(xin),同時在module數據表中添加(jia)新(xin)(xin)的(de)(de)(de)(de)(de)模塊(kuai)(kuai),就(jiu)(jiu)實(shi)現的(de)(de)(de)(de)(de)新(xin)(xin)模塊(kuai)(kuai)對老(lao)項(xiang)目的(de)(de)(de)(de)(de)集成!這一(yi)切可(ke)(ke)以(yi)說(shuo)與原(yuan)項(xiang)目是解耦合的(de)(de)(de)(de)(de),它們可(ke)(ke)以(yi)在不(bu)同的(de)(de)(de)(de)(de)解決方案(an)中完成,各自負責各位的(de)(de)(de)(de)(de)業(ye)務邏輯!
感謝各位對大叔框架的支持!
同時(shi)希(xi)望大家多多支持(chi)咱們.Net跨平臺社區,支持(chi)善友大牛!