OOP继承技巧:BASECONTROLLER与BASEAPICONTROLLER
BaseController与BaseApiController类别技巧不算是ASP.NET MVC或ASP.NET Web API的技术,它是一个OOP(Object-oriented programming,面向对象程序设计)继承的应用,这在早期Web Forms就已经被大量使用,因为它只是单纯的OOP继承应用,并不会被语言或框架所限制。
ASP.NET MVC - CONTROLLER类别
我们先来看看我们在进行开发的Controller类别继承关系:
IController继承关系

ControllerBase类别继承自IController介面,Controller类别继承自ControllerBase类别,而ControllerBase与Controller都是抽象类别:
- <font><font> public abstract class ControllerBase : IController {}</font></font><font></font><font><font>
- public abstract class Controller : ControllerBase, IActionFilter, IAuthenticationFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, IAsyncManagerContainer {} </font></font><font></font>
而我们开发者所在的ASP.NET MVC的Controller都是继承自Controller抽象类别,Controller抽象类别提供开发者所需的大部分功能:
- <font><font> public class HomeController : Controller {}
- </font></font>
从程序设计的角度来看,ASP.NET MVC的Controller也只是一个类别。如果你发现自己在其他Controller写了完全相同逻辑的源程序(相同的成员、属性或方法等),那么我们有非常合理的理由来建立一个共用的基础类别,之后将Controller里相同的成员、属性或方法往上层的基础类别移动,Controller只需重新继承此基础类别,就能发挥面向对象的继承的优势。

BaseController
BaseController是继承自Controller的类别,用于集中共用源程序让底下操作的Controller继承使用。
BASECONTROLLER - 数据库对象初始化
以Northwind数据库为例,使用基架多产生几个Controller类别(ProductsController、OrdersController、OrderDetailsController…),分析这些所有Controller类别会发现有一个成员会不断重覆出现在所有的Controller类别中:
- <font><font> private NorthwindEntities db = new NorthwindEntities();
- </font></font>
这里不讨论Repository模式或IoC的应用。
新增一个BaseController类别并继承Controller抽象类别,然后将产生db执行个体的源程序移至BaseController类别:
- <font><font> public class BaseController : Controller</font></font><font></font><font><font>
- {</font></font><font></font><font><font>
- protected NorthwindEntities db = new NorthwindEntities();</font></font><font></font><font><font>
- } </font></font><font></font>
注意,为了让子类别可以存取,存取修饰词不能是private。修改MVC Controller所继承的类别(以ProductsController为例):
- <font><font> public class ProductsController : BaseController</font></font><font></font><font><font>
- {</font></font><font></font><font><font>
- // 可删除。</font><font>注释是为让读者了解。</font></font><font></font><font><font>
- // private NorthwindEntities db = new NorthwindEntities();</font></font><font></font><font><font>
- }</font></font><font></font>
BASECONTROLLER - 指定TITLE
基架系统产生的View Page,每一页面的title值是在View Page里去指定,当要一一指定每一个页面title值时非常不便(你要开启每一个Action方法对应的View Page再一一修改)。
- <font><font> @{</font></font><font></font><font><font>
- ViewBag.Title = "Index";</font></font><font></font><font><font>
- } </font></font><font></font>
我们希望直接在Action方法里去指定title的值。把View Page里的指定title的源程序删除,然后在BaseController里新增一个Title属性:
- <font><font> public class BaseController : Controller</font></font><font></font><font><font>
- {</font></font><font></font><font><font>
- protected NorthwindEntities db = new NorthwindEntities();</font></font><font></font><font><font>
- // 新增Title属性</font></font><font></font><font><font>
- protected string Title {</font></font><font></font><font><font>
- set</font></font><font></font><font><font>
- {</font></font><font></font><font><font>
- ViewBag.Title = value;</font></font><font></font><font><font>
- } </font></font><font></font><font><font>
- }</font></font><font></font><font><font>
- } </font></font><font></font>
在继承BaseController类别的MVC Controller类别中就能直接进行title的设置:
- <font><font> public class ProductsController : BaseCont</font></font><font></font><font><font>
- {</font></font><font></font><font><font>
- public ActionResult Index()</font></font><font></font><font><font>
- {</font></font><font></font><font><font>
- // 指定Title属性</font></font><font></font><font><font>
- Title = "产品首页";</font></font><font></font><font><font>
- return View(db.Products.ToList());</font></font><font></font><font><font>
- }</font></font><font></font><font><font>
- // 省略</font></font><font></font><font><font>
- } </font></font><font></font>
View Page - Title
如果你有些专属于此系列MVC Controller的Action Filters,也能在BaseController里去覆写(Override)而继承的MVC Controller会直接生效。
- <font><font> public class BaseController : Controller</font></font><font></font><font><font>
- {</font></font><font></font><font><font>
- // 覆写ActionFilters</font></font><font></font><font><font>
- protected override void OnActionExecuting(ActionExecutingContext filterContext)</font></font><font></font><font><font>
- {</font></font><font></font><font><font>
- log("OnActionExecuting", filterContext.RouteData);</font></font><font></font><font><font>
- }</font></font><font></font><font><font>
- private void log(string method, RouteData routeData)</font></font><font></font><font><font>
- {</font></font><font></font><font><font>
- // Log源程序</font></font><font></font><font><font>
- }</font></font><font></font><font><font>
- } </font></font><font></font>
Action Filters本身是一种AOP 设计,在BaseController类别里覆写Action Filters的方式并不是很好的方式。这里要清楚类别继承的应用情境与AOP的应用情境是不同的。
BASEAPICONTROLLER
在ASP.NET Web API 2里的应用等同于Web Form与ASP.NET MVC的应用方式,新增BaseApiController并继承ApiController,然后操作共用源程序,并让其他子ApiController继承BaseApiController。
view source print ?
- <font><font> public class BaseApiController : ApiController</font></font><font></font><font><font>
- {</font></font><font></font><font><font>
- // 共用源程序</font></font><font></font><font><font>
- }</font></font><font></font>
不论是ASP.NET MVC或ASP.NET Web API 2本身是都大量OOP的实践,而我们要去‘承先启后’都不会太难。另外,像一些如NLog日志方法的初始化也适合由BaseController / BaseApicontroller来提供。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
