第 3 章 ASP.NET Core 核心特性
3.3 依賴注入
通常情況下,應用程序由多個組件構成,而組件與組件之間往往存在依賴關系
當我們需要獲取數(shù)據(jù)時,通常的做法是實例化依賴的類,然后調(diào)用類里面的方法,但是這種依賴方式會增加調(diào)用方和被調(diào)用方之間的耦合,也會增加應用程序維護成本及靈活性,同時增加了單元測試的難度
為了解決這一問題,需要用到依賴倒置原則,高層不直接依賴低層,兩者均依賴抽象
public class Book
{
}
public interface IDataService
{
List<Book> GetAllBooks();
}
public class DataService : IDataService
{
public List<Book> GetAllBooks()
{
return new List<Book>();
}
}
public class DisplayDataService
{
private readonly IDataService _dataService;
public DisplayDataService(IDataService dataService)
{
_dataService = dataService;
}
public void ShowData()
{
var data = _dataService.GetAllBooks();
}
}
接下來,只需要在實例化 DisplayDataService 的時候,在構造函數(shù)傳入一個 IDataService 接口的具體實現(xiàn)即可
IDataService dataService = new DataService();
DisplayDataService displayDataService = new DisplayDataService(dataService);
除了構造函數(shù)注入之外,還有屬性注入和方法注入
當應用程序中有多處要用到依賴注入時,就需要一個專門的類來負責管理創(chuàng)建所需要的類并創(chuàng)建所有它可能要用到的依賴,這個類就是依賴注入容器,也可以稱為控制反轉(zhuǎn)容器,IOC 容器
在 ASP.NET Core 中,所有被放入依賴注入容器的類型或組件被稱為服務
容器中的服務有兩種類型:第一種是框架服務,它們是 ASP.NET Core 框架的組成部分;另一種是應用服務,所有由用戶放到容器中的服務都屬于這一類
在 ASP.NET Core 內(nèi)置的依賴注入容器中,服務的生命周期有如下3種類型:
- Singleton:容器會創(chuàng)建并共享服務的單例,且一直會存在于應用程序的整個生命周期內(nèi)
- Transient:每次服務被請求時,總會創(chuàng)建新實例
- Scoped:在每一次請求時會創(chuàng)建服務的新實例,并在這個請求內(nèi)一直共享這個實例
3.4 MVC
MVC 是模型、視圖、控制器的縮寫,它是 Web 應用程序中一種常見的架構模式,最主要的優(yōu)點是實現(xiàn)了關注點分離
在 ASP.NET Core MVC 框架中,除了 Controller、Model 和 Action 外,它還包括路由、模型綁定、模型驗證和過濾器等功能
路由的主要功能是根據(jù)預先配置的路由信息對客戶端傳來的請求進行路由映射,映射完成后,再將請求傳給對應的路由處理器處理
對于 ASP.NET Core MVC,定義路由的方法有以下兩種:
- 基于約定的路由
- 特性路由
基于約定的路由需要在 Startup 類中指明,具體來說,應該在配置 MVC 中間件時來設置路由約定
app.UseMvc(routes =>
{
routes.MapRoute("default",template: "{controller}/{action}");
});
以下約定為 controller 和 action 設置了默認值,參數(shù) id 后面有一個問號,說明這個參數(shù)時可選的,在 URL 中有無此項都可以,注意,一個 URL 模板中只能有一個可選參數(shù),并且只能放在最后
app.UseMvc(routes =>
{
routes.MapRoute("default",template: "{controller=Home}/{action=Index}/{id?}");
});
指定參數(shù)時,也可以添加約束
app.UseMvc(routes =>
{
routes.MapRoute("default",template: "{controller=Home}/{action=Index}/{id:int}");
});
特性路由只需要在 Controller 類或 Action 方法上添加 [Route] 特性即可
[Route("Home")]
public class HomeController : Controller
{
[Route("Index")]
public IActionResult Index()
{
return View();
}
}
當 Controller 需要依賴其他服務時,通常的做法是使用構造函數(shù)注入所需要的服務,當程序運行時,ASP.NET Core 會在創(chuàng)建 Controller 時自動從其依賴注入的容器中獲取所有依賴的服務,需要注意的是,所注入的服務必須存在于容器中,否則會發(fā)生異常
Action 的返回結果有以下4類:
- StatusCode
- ObjectResult
- 重定向結果
- 內(nèi)容結果
模型綁定:將 HTTP 請求中的數(shù)據(jù)映射到 Action 中參數(shù)的過程
ASP.NET Core MVC 模型綁定特性:
- [FromHeader]
- [FromQuery]
- [FromServices]
- [FromRoute]
- [FromForm]
- [FromBody]
還有兩個特性用于指明參數(shù)是否必須使用綁定:
- BindRequiredAttribute
- BindNeverAttribute
模型驗證:指數(shù)據(jù)被使用之前的驗證過程,它發(fā)生在模型綁定之后
數(shù)據(jù)注解通常用于驗證,只要為類的屬性添加需要的數(shù)據(jù)注解驗證特性即可:
- [Required]
- [MinLength(10)]
- [Url]
- [Range(1,5)]
在 Controller 內(nèi)的 Action 中,要檢查一個對象是否滿足指定的條件,只要調(diào)用 ModelState.IsVaild 屬性,其中 ModelState 是 ControllerBase 類的屬性
ASP.NET Core MVC 提供兩種創(chuàng)建自定義驗證的方法:
- 創(chuàng)建新特性,并使它繼承自 ValidationAttribute 類
- 使待驗證的 Model 實現(xiàn) IValidatableObject 接口
過濾器:與中間件很相似,在 ASP.NET Core MVC 中,它們能夠在某些功能的前后執(zhí)行,由此形成一個管道
ASP.NET Core MVC 提供了以下5種類型的過濾器:
- Authorization
- Resource
- Action
- Exception
- Result
當要創(chuàng)建過濾器時,應該實現(xiàn) IXXXFilter 或 IAsyncXXXFilter,前者同步,后者異步,實現(xiàn)一個即可
在 startup 種注冊過濾器會使它影響到應用中的每個 Action,如果要僅為一個或少數(shù)幾個 Action 添加過濾器,就得使用特性,ASP.NET Core 為每一種類型的過濾器都定義了相應的特性
如果以特性的方式使用包含依賴項的過濾器時,就會出錯,因為在自定義特性的構造函數(shù)中定義的接口類型的參數(shù)并不是有效的特性參數(shù),此時需要使用 [ServiceFilter] 特性或者 [TypeFilter] 特性,并設置它們的 Type 屬性為自定義過濾器類型
[ServiceFilter] 特性與 [TypeFilter] 特性的區(qū)別是前者會從容器中獲取過濾器實例,而后者不會,它使用 ObjectFactory 對指定的過濾器類型進行實例化,如果使用前者,需要在 Startup 類的 ConfigureServices 方法中將該過濾器添加到容器中
????
本文摘自 :https://blog.51cto.com/u