這一節要來介紹DI依賴注入,這是什麼東西呢?
其實我們一開始就使用到了
builder.Services.AddDbContext<KcgContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("KcgDatabase")));
以上這個部分就是依賴注入我們資料庫物件,所以之後我們在Controller就可以來使用這個服務
那為什麼要做DI依賴注入呢?
第一個是我們要將程式給拆分出去,像是我們Controller之後只會留下控制邏輯
其他像是商業邏輯或資料處理邏輯,我們就會另外寫去Service之中
還有就是比較進階的IoC或依賴反轉等等,都會使用到DI依賴注入的方式去實現
那我們今天先教基本的依賴注入該怎麼做,哪裡要搬出去到Service
首先先建立一個專門放Service的資料夾,再來就建立一個NewsService.cs的類別

那我們今天要搬什麼東西過來呢,可以先搬index這頁的內容
public class NewsService
{
private readonly KcgContext _context;
public NewsService(KcgContext context)
{
_context = context;
}
public async Task<List<NewsDto>> 取得新聞列表()
{
var result = from a in _context.News
join b in _context.Department on a.DepartmentId equals b.DepartmentId
join c in _context.Employee on a.UpdateEmployeeId equals c.EmployeeId
select new NewsDto
{
Click = a.Click,
Enable = a.Enable,
EndDateTime = a.EndDateTime,
NewsId = a.NewsId,
StartDateTime = a.StartDateTime,
Title = a.Title,
UpdateDateTime = a.UpdateDateTime,
UpdateEmployeeName = c.Name,
DepartmentName = b.Name
};
return await result.ToListAsync();
}
}
如此我們就將取資料程式的部分搬移過來了
接著要回到NewsController.cs中取得NewsService服務
跟之前取得資料庫是一樣的用法
接著我們就可以在下面方法中使用NewsService取得新聞列表了
private readonly NewsService _newsService;
public NewsController(NewsService newsService)
{
_newsService = newsService;
}
public async Task<IActionResult> Index()
{
var result = await _newsService.取得新聞列表();
return View(result);
}
如此我們controller就變得相當的整潔
雖然因為今天只有單純的取資料看起來似乎沒必要移過去,但隨著程式複雜度增加
到時可能會有控制邏輯、商業邏輯和取資料邏輯,這時我們就會將控制邏輯放在controller
而其他邏輯則移到Service去,讓後續維護可以更清晰
最後我們還要在Program.cs依賴注入NewsService後才能使用
builder.Services.AddScoped<NewsService>();
我們這邊在示範一段取得單一新聞的頁面
public async Task<NewsDto> 取得新聞詳細資訊(Guid newsId)
{
var result = from a in _context.News
join b in _context.Department on a.DepartmentId equals b.DepartmentId
join c in _context.Employee on a.UpdateEmployeeId equals c.EmployeeId
where a.NewsId == newsId
select new NewsDto
{
Click = a.Click,
Enable = a.Enable,
EndDateTime = a.EndDateTime,
NewsId = a.NewsId,
StartDateTime = a.StartDateTime,
Title = a.Title,
UpdateDateTime = a.UpdateDateTime,
UpdateEmployeeName = c.Name,
DepartmentName = b.Name,
Content = a.Contents
};
//取得上傳資料的邏輯
return await result.FirstOrDefaultAsync();
}
如上面,我們取得新聞可能除了新聞本身,還有可能要取得相關附件的邏輯,所以如此一來程式可能更加複雜
public async Task<IActionResult> Details(Guid? id)
{
if (id == null)
{
return NotFound();
}
var news = await _newsService.取得新聞詳細資訊(id.Value);
if (news == null)
{
return NotFound();
}
return View(news);
}
回到controller這邊,我們就只保留控制邏輯,處理邏輯則呼叫service取得,如上
這樣維護起來思路就很清晰,controller這邊可以看整體控制運作的情況,想要進一步看處理的邏輯,則再去service裡面看
當然還有很多不同的設計模式或公司文化的寫法,這就看實務上怎麼去運用,這邊就提供一個最基本的寫法給大家參考
接著大家可以試著把新增跟修改的部分,也移去service,這邊就不在做示範了
我範例檔的部分有全部修改完的程式,供大家參考
範例檔:下載