新聞中心
本文轉(zhuǎn)載自微信公眾號「 碼農(nóng)讀書」,作者 碼農(nóng)讀書。轉(zhuǎn)載本文請聯(lián)系 碼農(nóng)讀書公眾號。

創(chuàng)新互聯(lián),為您提供成都網(wǎng)站建設、成都網(wǎng)站制作、網(wǎng)站營銷推廣、網(wǎng)站開發(fā)設計,對服務水處理設備等多個行業(yè)擁有豐富的網(wǎng)站建設及推廣經(jīng)驗。創(chuàng)新互聯(lián)網(wǎng)站建設公司成立于2013年,提供專業(yè)網(wǎng)站制作報價服務,我們深知市場的競爭激烈,認真對待每位客戶,為客戶提供賞心悅目的作品。 與客戶共同發(fā)展進步,是我們永遠的責任!
你可以遵循一些最佳實踐來寫出更干凈的 Controller,一般我們稱這種方法寫出來的 Controller 為瘦Controller,瘦 Controller 的好處在于擁有更少的代碼,更加單一的職責,也便于閱讀和維護,而且隨著時間的推移也容易做 Controller 的多版本。
這篇文章我們一起討論那些讓 Controler 變胖變臃腫的一些壞味道,并且一起探索讓 Controller 變瘦的手段,雖然我的一些在 Controller 上的最佳實踐可能不是專業(yè)的,但我每一步都提供相關源代碼來進行優(yōu)化,接下來的章節(jié)中,我們會討論什么是 胖Controller,什么是 壞味道,什么是 瘦Controller,它能帶給我們什么福利?并且如何讓 Controller 變瘦,變簡單,利測試,易維護。
從 Controller 中移除數(shù)據(jù)層代碼
當在寫 Controller 的時候,你應該遵守 單一職責,也就意味著你的 Controller 只需做一件事情,換句話說,只有一個因素或者唯一一個因素能讓你修改 Controller 中的代碼,如果有點懵的話,考慮下面的代碼片段,它將 數(shù)據(jù)訪問代碼 糅進了 Controller 。
- public class AuthorController : Controller
- {
- private AuthorContext dataContext = new AuthorContext();
- public ActionResult Index(int authorId)
- {
- var authors = dataContext.Authors
- .OrderByDescending(x=>x.JoiningDate)
- .Where(x=>x.AuthorId == authorId)
- .ToList();
- return View(authors);
- }
- //Other action methods
- }
請注意上面的代碼在 Action 中使用了 dataContext 從數(shù)據(jù)庫讀取數(shù)據(jù),這就違反了單一職責原則,并直接導致了 Controller 的臃腫。
假如后續(xù)你需要修改 數(shù)據(jù)訪問層 代碼,可能基于更好的性能或者你能想到的原因,這時候只能被迫在 Controller 中修改,舉個例子吧:假如你想把上面的 EF 改成 Dapper 去訪問底層的 Database,更好的做法應該是單獨拎出來一個 repository 類來操控 數(shù)據(jù)訪問 相關的代碼,下面是更新后的 AuthorController。
- public class AuthorController : Controller
- {
- private AuthorRepository authorRepository = new AuthorRepository();
- public ActionResult Index(int authorId)
- {
- var authors = authorRepository.GetAuthor(authorId);
- return View(authors);
- }
- //Other action methods
- }
現(xiàn)在 AuthorController 看起來是不是精簡多了,上面的代碼是不是就是最佳實踐呢?不完全是,為什么這么說呢?上面這種寫法導致 Controller 變成了 數(shù)據(jù)訪問組件,取出數(shù)據(jù)后必然少不了一些業(yè)務邏輯處理,這就讓 Controller 違反了 單一職責,對吧,更通用的做法應該是將 數(shù)據(jù)訪問邏輯 封裝在一個 service 層,下面是優(yōu)化之后的 AuthorController 類。
- public class AuthorController : Controller
- {
- private AuthorService authorService = new AuthorService();
- public ActionResult Index(int authorId)
- {
- var authors = authorService.GetAuthor(authorId);
- return View(authors);
- }
- //Other action methods
- }
再看一下 AuthorService 類,可以看到它利用了 AuthorRepository 去做 CURD 操作。
- public class AuthorService
- {
- private AuthorRepository authorRepository = new AuthorRepository();
- public Author GetAuthor (int authorId)
- {
- return authorRepository.GetAuthor(authorId);
- }
- //Other methods
- }
避免寫大量代碼做對象之間映射
在 DDD 開發(fā)中,經(jīng)常會存在 DTO 和 Domain 對象,在數(shù)據(jù) Input 和 Output 的過程中會存在這兩個對象之間的 mapping,按照普通的寫法大概就是這樣的。
- public IActionResult GetAuthor(int authorId)
- {
- var author = authorService.GetAuthor(authorId);
- var authorDTO = new AuthorDTO();
- authorDTO.AuthorId = author.AuthorId;
- authorDTO.FirstName = author.FirstName;
- authorDTO.LastName = author.LastName;
- authorDTO.JoiningDate = author.JoiningDate;
- //Other code
- ......
- }
可以看到,這種一一映射的寫法讓 Controller 即時膨脹,同時也讓 Controller 增加了額外的功能,那如何把這種 模板式 代碼規(guī)避掉呢?可以使用專業(yè)的 對象映射框架 AutoMapper 去解決,下面的代碼展示了如何做 AutoMapper 的配置。
- public class AutoMapping
- {
- public static void Initialize()
- {
- Mapper.Initialize(cfg =>
- {
- cfg.CreateMap
(); - //Other code
- });
- }
- }
接下來可以在 Global.asax 中調(diào)用 Initialize() 初始化,如下代碼所示:
- protected void Application_Start()
- {
- AutoMapping.Initialize();
- }
最后,可以將 mapping 邏輯放在 service 層中,請注意下面的代碼是如何使用 AutoMapper 實現(xiàn)兩個不兼容對象之間的映射。
- public class AuthorService
- {
- private AuthorRepository authorRepository = new AuthorRepository();
- public AuthorDTO GetAuthor (int authorId)
- {
- var author = authorRepository.GetAuthor(authorId);
- return Mapper.Map
(author); - }
- //Other methods
- }
避免在 Controller 中寫業(yè)務邏輯
盡量避免在 Controller 中寫 業(yè)務邏輯 或者 驗證邏輯, Controller 中應該僅僅是接收一個請求,然后被下一個 action 執(zhí)行,別無其它,回到剛才的問題,這兩種邏輯該怎么處理呢?
- 業(yè)務邏輯
這些邏輯可以封裝 XXXService 類中,比如之前創(chuàng)建的 AuthorService。
- 驗證邏輯
這些邏輯可以用 AOP 的操作手法,比如將其塞入到 Request Pipeline 中處理。
使用依賴注入而不是硬組合
推薦在 Controller 中使用依賴注入的方式來實現(xiàn)對象之間的管理,依賴注入是 控制反轉(zhuǎn) 的一個子集,它通過外部注入對象之間的依賴從而解決內(nèi)部對象之間的依賴,很拗口是吧!
一旦你用了依賴注入方式,就不需要關心對象是怎么實例化的,怎么初始化的,下面的代碼展示了如何在 AuthorController 下的構造函數(shù)中實現(xiàn) IAuthorService 對象的注入。
- public class AuthorController : Controller
- {
- private IAuthorService authorService = new AuthorService();
- public AuthorController(IAuthorService authorService)
- {
- this.authorService = authorService;
- }
- // Action methods
- }
使用 action filer 消除 Controller 中的重復代碼
可以利用 action filter 在 Request pipeline 這個管道的某些點上安插一些你的自定義代碼,舉個例子,可以使用 ActionFilter 在 Action 的執(zhí)行前后安插一些自定義代碼,而不是將這些業(yè)務邏輯放到 Controller 中,讓 Controller 不必要的膨脹,下面的代碼展示了如何去實現(xiàn)。
- [ValidateModelState]
- [HttpPost]
- public ActionResult Create(AuthorRequest request)
- {
- AuthorService authorService = new AuthorService();
- authorService.Save(request);
- return RedirectToAction("Home");
- }
總的來說,如果一個 Controller 被賦予了幾個職責,那么只要是其中任何一個職責的原因,你都必須對 Controller 進行修改,總的來說,一定要堅守 單一原則。
本文題目:如何在ASP.NETCore中寫出更干凈的Controller
網(wǎng)頁鏈接:http://fisionsoft.com.cn/article/ccichdc.html


咨詢
建站咨詢
