public interface IInstanceId { string Id { get; } }
public class SingletonSvc : IInstanceId { public string Id { get; } = Guid.NewGuid().ToString("N")[..8]; }
public class ScopedSvc : IInstanceId { public string Id { get; } = Guid.NewGuid().ToString("N")[..8]; }
public class TransientSvc : IInstanceId { public string Id { get; } = Guid.NewGuid().ToString("N")[..8]; }
builder.Services.AddSingleton<IInstanceId, SingletonSvc>();
builder.Services.AddScoped<IInstanceId, ScopedSvc>();
builder.Services.AddTransient<IInstanceId, TransientSvc>();
app.MapGet("/di-demo", (IInstanceId s1, IInstanceId s2) =>
Results.Ok(new { singleton = s1.Id, scoped = s2.Id, transient1 = s1 is not ScopedSvc ? "见下" : "" }));
// 连续刷新页面:Singleton 的 Id 永不变;Scoped 的 Id 每个请求变;Transient 同一请求内解析两次也各不相同
步骤 3:多实现——策略注入与 Keyed Services
判题平台按语言分发判题器,是策略模式的教科书场景:
public interface ILanguageJudge { string Language { get; } Task<string> RunAsync(string code); }
public class CppJudge : ILanguageJudge { public string Language => "cpp"; /* ... */ public Task<string> RunAsync(string code) => Task.FromResult("WA"); }
public class JavaJudge : ILanguageJudge { public string Language => "java"; /* ... */ public Task<string> RunAsync(string code) => Task.FromResult("TLE"); }
builder.Services.AddScoped<ILanguageJudge, CppJudge>();
builder.Services.AddScoped<ILanguageJudge, JavaJudge>();
// 注入 IEnumerable<T> 拿到全部实现(Spring 注入 List<ILanguageJudge> 同款)
public class JudgeDispatcher(IEnumerable<ILanguageJudge> judges)
{
public Task<string> DispatchAsync(string lang, string code) =>
judges.FirstOrDefault(j => j.Language == lang)?.RunAsync(code)
?? throw new NotSupportedException($"语言 {lang} 未支持");
}
// .NET 8 具名注册:按 Key 精确取用(对应 @Qualifier)
builder.Services.AddKeyedScoped<ILanguageJudge, CppJudge>("cpp");
app.MapGet("/judge/cpp", ([FromKeyedServices("cpp")] ILanguageJudge j) => j.RunAsync("int main(){}"));
步骤 4:Options 模式(配置即服务)
builder.Services.Configure<JudgeOptions>(builder.Configuration.GetSection("Judge"));
public class JudgeDispatcher(IEnumerable<ILanguageJudge> judges, IOptions<JudgeOptions> opts)
{
public int Timeout => opts.Value.TimeoutSeconds; // 强类型配置
}