8-1.ASP.NET Core MVC 入門教學 - 基本DI依賴注入用法

ASP.NET Core MVC 入門教學

這一節要來介紹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,這邊就不在做示範了

我範例檔的部分有全部修改完的程式,供大家參考

 

範例檔:下載




Copyright © 凱哥寫程式 2022 | Powered by TalllKai ❤