在 ASP.NET Core 中使用套件達成自動註冊服務

在上一篇文章「建立 NuGet 套件,上傳到 nuget.org」中筆者建立了一個套件,本篇就來示範這個套件的使用方式。

平時在 ASP.NET Core 中,我們使用依賴注入(Dependency Injection, DI)的步驟如下:
註:本文使用 .NET 8 語法

假設我們有一個非常簡單的 UserService.cs
    
public class UserService
{
    public List<string> GetUsers()
    {
        return
        [
            "User1",
            "User2"
        ];
    }
}
    

在 UserController.cs 中會呼叫上面的 UserService.cs
    
[ApiController]
[Route("[controller]")]
public class UserController(UserService userService) : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return Ok(userService.GetUsers());
    }
}
    

直接執行時會出現以下錯誤:
    
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
      System.InvalidOperationException: Unable to resolve service for type 'UserService' while attempting to activate 'UserController'.
         at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ThrowHelperUnableToResolveService(Type type, Type requiredBy)
         at lambda_method3(Closure, IServiceProvider, Object[])
    

說明 UserService 沒有被註冊到 DI 服務中,所以我們需要在 Program.cs 檔案中手動註冊 UserService 服務才能正常執行:
    
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddScoped<UserService>();

var app = builder.Build();

app.Run();
    

如果有把 UserService 抽介面(interface)的話,就會有 IUserService :
    
public interface IUserService
{
    List<string> GetUsers();
}
    

UserService 會實作 IUserService 介面:
    
public class UserService : IUserService
{
    public List<string> GetUsers()
    {
        return
        [
            "User1",
            "User2"
        ];
    }
}
    

UserController 就會使用 IUserService:
    
[ApiController]
[Route("[controller]")]
public class UserController(IUserService userService) : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return Ok(userService.GetUsers());
    }
}
    

然後在 Program.cs 中就需要使用以下程式碼,標記在使用 IUserService 的地方需要自動提供 UserService 實例。
    
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddScoped<IUserService, UserService>();

var app = builder.Build();

app.Run();
    

所有有使用依賴注入(Dependency Injection, DI)的服務都需要在 Program.cs 中註冊,非常麻煩,而且隨著專案越來越大,在 Program.cs 中用來註冊 DI 的程式碼就會越來越多,甚至達到數十行。
使用 AutoServiceRegistration.AspNetCore 套件就可以透過在介面上繼承套件中的 IScopedService 介面來自動註冊。

安裝套件

先使用 NuGet 安裝 AutoServiceRegistration.AspNetCore 套件,或是使用 .NET CLI 執行以下指令安裝
	
dotnet add package AutoServiceRegistration.AspNetCore
    

在 Program.cs 檔案中增加以下程式碼啟用自動註冊的服務:
    
using AutoServiceRegistration.AspNetCore;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRegisterServices();

var app = builder.Build();

app.Run();
    

使用示範

回到剛剛的範例,只要在 IUserService 這個介面中繼承 IScopedService 即可,就不需要在 Program.cs 中使用 builder.Services.AddScoped<UserService>(); 註冊了。
    
public interface IUserService : IScopedService
{
    List<string> GetUsers();
}
    

除了 IScopedService 以外,還可以使用 ISingletonService 和 ITransientService ,會對應到 AddSingleton 和 AddTransient 這三個不同的生命週期。

參考資料:
nuget.org - AutoServiceRegistration.AspNetCore
GitHub - AutoServiceRegistration.AspNetCore

留言