上一篇我們初步完善了項目的DAL層和BLL層,本章我們簡單介紹下依賴注入,使用AutoFac替換系統自帶的容器,並配置下WebApi環境
一、IOC容器的使用
1、依賴倒置【DIP】
什么是DIP?即為依賴倒置,面向對象編程設計原則的一種,即細節應當依賴於抽象,要針對抽象(接口)編程,而不是針對實現細節編程。所以在第二章我們對DAL層和BLL層分別添加了接口層。
2、控制反轉【IOC】
什么是IOC?即為控制反轉,依賴倒置原則的一種實現方法。舉個例子來說:
①一個IPerson接口,存在一個Eat的方法,在實現類Person中,我們實現Eat方法返回結果;
②通常我們在其他類中調用Person類時,首先會添加引用,Person person=new Person()后,通過person.Eat()方法獲取到結果,但這違反了依賴導致原則;
③另外一種設計原則—里氏替換原則提到,所有引用基類的地方應當可以透明的使用其子類的對象,所以這里我們可以使用IPerson person=new Person()實現同樣的效果,但是這樣做反而依賴了IPerson和Person兩個對象;
④此外,若Person類后續需要改為大人和小孩,原先系統中如有幾十處依賴了Person對象,我們要一下修改幾十處,這是極不合理的,所以最佳方案是我們只依賴IPerson,如何實現?通過依賴注入。
3、依賴注入【DI】
DI即為依賴注入,控制反轉的一種實現方法,它提供一種機制,將需要依賴對象的引用傳遞給被依賴對象,實現方法有構造函數注入,屬性注入,方法注入,像在DAL和BLL中我們使用的就是構造函數注入。
4、IOC容器
隨着系統的不斷完善,依賴關系越來越多,手動方式處理會比較麻煩,所以我們可以借助IOC容器,它是一種DI框架,使用它可以簡化我們的工作,通常它會包含依賴對象注入,對象生命周期管理,依賴關系映射等功能。
這里貼一張之前整理的文檔(部分內容引用了一篇博客,來源找不到了,若給原作者帶來困擾,請聯系刪除)
5、ASP.NET Core與IOC容器
ASP.NET Core中大量使用了DI(Dependency Injection)依賴注入,即在系統啟動時進行服務注冊,將服務添加至IOC容器中,其他的類則可以通過IOC容器請求這些服務的實例,並使用這些服務的功能。
ASP.NET Core內部是實現了IOC容器的,一共有三種:①Transient,服務每次請求都會生成一個實例;② Scoped,一次Web請求生成一個實例;③Singleton,只會產生一個實例直至應用程序停止;
在實際使用時我們需要指明映射關系,即接口與對應的實現類,但是我們發現目前我們的項目中有不少接口和實現類,難道要一個個注冊嗎?如果有幾十幾百個怎么辦呢?這里我們使用AtuoFac來實現程序集級別的注入,使用Nuget引用AutoFac依賴注入插件,如下:
6、IOC容器使用
6.1、准備工作
右擊依賴項,添加引用,將IBLL和IDAL勾選,另外我們要用到Model層里面的ViewModel,所以這里也一並勾上
這里我們是通過反射加載程序集的方式進行注冊,雖然程序上沒有添加依賴關系,當通過它們的接口引用其方法時還是需要引用它們,所以如下圖所示,BLL和DAL全部選擇輸出到BlogSystem.Core項目的Debug文件夾下:
6.2、 替換系統容器
①在Program的CreateHostBuilder方法中將系統的服務支持工廠替換為AutoFac的工廠(Core3.1新方式):
②在Startup中添加ConfigureContainer方法,獲取DAL和BLL的程序集並注冊,如下:
二、WebApi簡單配置
在Program類中有兩個方法:①ConfigureService方法內部我們可以進行服務的注冊;②Configure方法,可以配置注冊過的服務(管道中間件),來使用服務包含的特性或功能;
由於我們添加項目時使用的是空模板,所以這里我們需要手動添加一些服務,
1、注冊Controllers
在ConfigureService方法中添加,如下:
2、修改端點中間件
在configure方法中路由中間件會檢查應用中已經注冊的端點並使用,由於時WebAPI項目,所以這里我們將其改為映射控制器的方式,與此同時我們需要在控制器方法中使用特性路由(在控制器和方法上標注路由信息)
3、注冊數據庫服務(可忽略)
PS:這里其實可以不需要,因為我們在Model層的BlogSystemContext文件中OnConfiguring方法已經配置了數據庫,這樣操作反而調用了兩次BlogSystemContext類(感謝園友@盛盛盛的提醒)
1、首先為startup類新增一個構造函數,將IConfiguration注入進去,並賦值給靜態只讀字段,如下:
2、在appsettiongs.json中我們添加數據庫連接字符串,如下圖:
3、然后在startup類中的ConfigurationService中添加SQLServer的服務注冊
4、建立Controllers
在項目中建立Controllers文件夾,我們先建立一個UserController,繼承自ControllerBase,為其添加屬性路由 [Route("api/Users")]
,並為其添加標識[ApiController],它包含如下功能:①會自動要求使用屬性路由,②推斷參數的綁定源,③自動Http400響應,④錯誤狀態代碼問題的詳細信息,⑤Multipart/form-data請求推斷;
在構造函數中,我們注入IBLL服務接口;首先添加一個注冊功能,為其標識為HTTPOST並為其命名,實現如下:
我們在PostMan中添加測試數據,試着注冊一下,成功執行
5、密碼加密
上一步我們成功注冊了一個用戶,但是密碼沒有加密,這里我們使用MD5加密下密碼,簡單來說就是只要對密碼進行驗證操作就加密后和數據庫內的密碼進行對比。
1、在BlogSystem.Common項目下新建一個Helpers文件夾,在里面添加一個Md5Helper類,添加如下方法
using System;
using System.Security.Cryptography;
using System.Text;
namespace BlogSystem.Common.Helpers
{
public static class Md5Helper
{
public static string Md5Encrypt(string password)
{
//判斷非空
if (string.IsNullOrEmpty(password) || string.IsNullOrWhiteSpace(password))
{
return string.Empty;
}
var pwd = String.Empty;
using (MD5 md5 = MD5.Create())
{
byte[] buffer = Encoding.UTF8.GetBytes(password);
byte[] newBuffer = md5.ComputeHash(buffer);
foreach (var item in newBuffer)
{
pwd = string.Concat(pwd, item.ToString("X2"));
}
}
return pwd;
}
}
}
2、修改BLL中我們的注冊方法,以及用戶登錄,修改用戶密碼方法中涉及到密碼操作的部分;此外發現注冊方法和修改密碼方法沒有返回值不利於后台判斷,於是修改了方法邏輯,同時記得修改下IBLL的方法返回值,完成操作后記得重新生成解決方案覆蓋下舊的dll,否則容器注入會提示錯誤。如下:
/// <summary>
/// 用戶注冊
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public async Task<bool> Register(RegisterViewModel model)
{
//判斷賬戶是否存在
if (!await _userRepository.GetAll().AnyAsync(m => m.Account == model.Account))
{
var pwd = Md5Helper.Md5Encrypt(model.Password);
await _userRepository.CreateAsync(new User()
{
Account = model.Account,
Password = pwd
});
return true;
}
return false;
}
/// <summary>
/// 用戶登錄
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public async Task<Guid> Login(LoginViewModel model)
{
var pwd = Md5Helper.Md5Encrypt(model.Password);
var user = await _userRepository.GetAll().FirstOrDefaultAsync(m => m.Account == model.Account && m.Password == pwd);
return user != null ? user.Id : new Guid();
}
/// <summary>
/// 修改用戶密碼
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public async Task<bool> ChangePassword(ChangePwdViewModel model)
{
var oldPwd = Md5Helper.Md5Encrypt(model.OldPassword);
var newPwd = Md5Helper.Md5Encrypt(model.NewPassword);
if (await _userRepository.GetAll().AnyAsync(m => m.Id == model.UserId && m.Password == oldPwd))
{
var user = await _userRepository.GetAll().FirstOrDefaultAsync(m => m.Id == model.UserId && m.Password == oldPwd);
user.Password = newPwd;
await _userRepository.EditAsync(user);
return true;
}
return false;
}
3、修改下Controller中的注冊方法的邏輯,從后台把之前注冊的賬號刪除,重新注冊一個賬號,完成操作
本章完~
本人知識點有限,若文中有錯誤的地方請及時指正,方便大家更好的學習和交流。
本文部分內容參考了博客園幾位大佬的視頻和文章,僅為學習和交流,視頻地址如下:
solenovex,ASP.NET Core MVC 2.x 全面教程
solenovex,ASP.NET Core 3.x 入門視頻
角落的白板報,《從零開始學ASP.NET Core與Entity Framework Core 》
老張的哲學,最全的 netcore 3.0 升級實戰方案