ASP.NET Core / .NET の DI でよく出る Unable to resolve service for type 'XXX' while attempting to activate 'YYY'。登録漏れか、寿命の取り違えか、実装型の取り違えかがほとんど。
この記事では原因の型と切り分け手順をざっくりまとめる。
for type 'A' while activating 'B' は、「B を作ろうとして依存 A がコンテナに無い」Program.cs(または Startup)の登録と、例外の A / B の型名を突き合わせるValidateOnBuild / ValidateScopes を有効にすると起動時に気づきやすいUnable to resolve service for type 'IOrderRepository'
while attempting to activate 'OrdersController'.
IOrderRepository)// 足りない例
// builder.Services.AddScoped<IOrderRepository, OrderRepository>();
public class OrdersController(IOrderRepository repo) { }
// NG: 具象だけ
builder.Services.AddScoped<OrderRepository>();
// コンストラクタは IOrderRepository → 解決できない
// OK
builder.Services.AddScoped<IOrderRepository, OrderRepository>();
AddDbContext、AddHttpClient、AddAuthentication など「セットで登録する系」を呼んでいないと、内側の型が足りない、となりやすい。
WebApplicationFactory で落ちる → テスト側の ConfigureTestServices で上書きしすぎ / 消しすぎBackgroundService から GetRequiredService → スコープ未作成や登録漏れIOptions<T> が欲しいのに Configure<T> していないILogger<T> は通常フレームワークが登録済み。自前コンテナを組むと足りないことがあるProgram.cs / AddInfrastructure() 等で A の登録を検索IServiceCollection を別経路で見ていないか確認builder.Host.UseDefaultServiceProvider(o =>
{
o.ValidateScopes = true;
o.ValidateOnBuild = true; // 起動時に解決できるかざっくり検証
});
AddXxx(this IServiceCollection) に登録を集約し、起動で 1 回呼ぶAddScoped<IFoo, Foo>() 形式で揃える関連: DI のスコープとライフサイクル
ValidateOnBuild で起動時に寄せる