ASP.NET Core DIでサービスをControllerから使用する
DIは、クラスが必要とする別のクラスを外部から渡す仕組みです。
ASP.NET CoreにはDIコンテナーが標準で用意されています。
DIを使う理由は、単にnewを書く場所を移すためではありません。Controllerが具象クラスの生成方法や寿命を決めず、必要な機能だけを宣言できるようにするためです。これにより、本番用の実装とテスト用の実装を呼び出し側を変えずに交換できます。
サービスを作成する
GreetingService.cspublic interface IGreetingService
{
string CreateMessage(string name);
}
public sealed class GreetingService : IGreetingService
{
public string CreateMessage(string name)
{
return $"こんにちは、{name}さん。";
}
}interfaceには利用できる処理を定義し、classへ実際の処理を書きます。
DIコンテナーへ登録する
Program.csvar builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddScoped<IGreetingService, GreetingService>();
var app = builder.Build();
app.MapControllers();
app.Run();IGreetingServiceが必要な場所へ、GreetingServiceを渡す設定です。
Controllerで受け取る
GreetingController.csusing Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/greeting")]
public sealed class GreetingController(IGreetingService greetingService)
: ControllerBase
{
[HttpGet]
public IActionResult Find([FromQuery] string name)
{
return Ok(new
{
message = greetingService.CreateMessage(name),
});
}
}GET /api/greeting?name=山田へアクセスすると、Controllerの作成時にサービスが自動で渡されます。
Controller内でnew GreetingService()を書く必要はありません。
登録方法の違い
登録時には、依存するオブジェクトをいつまで共有するかも決めます。寿命が長いほど効率的とは限らず、リクエスト固有の状態をSingletonへ持たせると、別の利用者の処理と共有される危険があります。
| 登録方法 | インスタンスの期間 |
|---|---|
AddTransient | 取得するたびに新しく作る |
AddScoped | 1回のHTTPリクエスト内で共有する |
AddSingleton | アプリケーション全体で共有する |
Web APIのサービスやデータベース関連では、まずAddScopedを使うことが多いです。
Singletonはアプリケーション全体で残るため、寿命が短いScopedのサービスをコンストラクターで受け取る設計は避けます。
DIを使うと、クラス内で依存先を作成せずに済み、実装の交換やテストがしやすくなります。