用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/rudironsoni/Synaxis --skill dotnet-csharp-dependency-injection命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Routes .NET/C# work to domain skills. Loads coding-standards for code paths.
正在显示 SKILL.md
基于 SOC 职业分类
| name | dotnet-csharp-dependency-injection |
| description | Registers and resolves services with MS DI. Keyed services, scopes, decoration, lifetimes. |
| license | MIT |
| targets | ["*"] |
| category | fundamentals |
| subcategory | di-and-services |
| tags | ["csharp","dotnet","skill","dependency-injection","di"] |
| version | 1.0.0 |
| author | dotnet-agent-harness |
| invocable | true |
| related_skills | ["dotnet-csharp-configuration","dotnet-validation-patterns","dotnet-architecture-patterns"] |
| claudecode | {"allowed-tools":["Read","Grep","Glob","Bash","Write","Edit"]} |
| codexcli | {"short-description":".NET skill guidance for csharp tasks"} |
| opencode | {"allowed-tools":["Read","Grep","Glob","Bash","Write","Edit"]} |
| copilot | {} |
| geminicli | {} |
| antigravity | {} |
Advanced Microsoft.Extensions.DependencyInjection patterns for .NET applications. Covers service lifetimes, keyed services (net8.0+), decoration, factory delegates, scope validation, and hosted service registration.
Cross-references: [skill:dotnet-csharp-async-patterns] for BackgroundService async patterns,
[skill:dotnet-csharp-configuration] for IOptions<T> binding.
| Lifetime | Registration | When to Use |
|---|---|---|
| Transient | AddTransient<T>() | Lightweight, stateless services. New instance per injection. |
| Scoped | AddScoped<T>() | Per-request state (EF Core DbContext, unit of work). |
| Singleton | AddSingleton<T>() | Thread-safe, stateless, or shared state (caches, config). |
Never inject a shorter-lived service into a longer-lived one:
// WRONG -- scoped DbContext captured in singleton = same context for all requests
builder.Services.AddSingleton<OrderService>(); // singleton
builder.Services.AddScoped<AppDbContext>(); // scoped -- CAPTIVE!
// CORRECT -- use IServiceScopeFactory in singletons
public sealed class OrderService(IServiceScopeFactory scopeFactory)
{
public async Task ()
{
scope = scopeFactory.CreateScope();
db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
db.Orders.Where(o => o.IsPending).ToListAsync(ct);
}
}
```text
```csharp
builder = WebApplication.CreateBuilder();
host = Host.CreateDefaultBuilder()
.UseDefaultServiceProvider(options =>
{
options.ValidateScopes = ;
options.ValidateOnBuild = ;
})
.Build();
```text
---
```csharp
builder.Services.AddScoped<IOrderRepository, SqlOrderRepository>();
```csharp
```csharp
builder.Services.AddScoped<INotifier, EmailNotifier>();
builder.Services.AddScoped<INotifier, SmsNotifier>();
builder.Services.AddScoped<INotifier, PushNotifier>();
{
{
( notifier notifiers)
{
notifier.NotifyAsync(message, ct);
}
}
}
```text
```csharp
builder.Services.AddScoped<IOrderService>(sp =>
{
repo = sp.GetRequiredService<IOrderRepository>();
logger = sp.GetRequiredService<ILogger<OrderService>>();
options = sp.GetRequiredService<IOptions<OrderOptions>>();
OrderService(repo, logger, options.Value.MaxRetries);
});
```text
Libraries should use `TryAdd` so applications can :
```csharp
builder.Services.TryAddScoped<IOrderRepository, DefaultOrderRepository>();
builder.Services.AddScoped<IOrderRepository, CustomOrderRepository>();
```text
---
Register resolve services a key, replacing the need named service patterns.
```csharp
builder.Services.AddKeyedScoped<ICache, RedisCache>();
builder.Services.AddKeyedScoped<ICache, MemoryCache>();
{
Task<Order?> GetAsync( id, CancellationToken ct = )
{
localCache.GetAsync<Order>(id.ToString(), ct)
?? distributedCache.GetAsync<Order>(id.ToString(), ct);
}
}
cache = sp.GetRequiredKeyedService<ICache>();
```text
> **net8+ only.** On earlier TFMs, use factory patterns a dictionary-based approach.
---
The built- container does natively support decoration. Use one of these approaches:
```csharp
builder.Services.AddScoped<SqlOrderRepository>();
builder.Services.AddScoped<IOrderRepository>(sp =>
{
inner = sp.GetRequiredService<SqlOrderRepository>();
logger = sp.GetRequiredService<ILogger<LoggingOrderRepository>>();
LoggingOrderRepository(inner, logger);
});
{
Task<Order?> GetByIdAsync( id, CancellationToken ct = )
{
logger.LogInformation(, id);
inner.GetByIdAsync(id, ct);
}
}
```text
```csharp
builder.Services.AddScoped<IOrderRepository, SqlOrderRepository>();
builder.Services.Decorate<IOrderRepository, LoggingOrderRepository>();
builder.Services.Decorate<IOrderRepository, CachingOrderRepository>();
```text
---
```
{
{
logger.LogInformation();
(!stoppingToken.IsCancellationRequested)
{
{
scope = scopeFactory.CreateScope();
processor = scope.ServiceProvider
.GetRequiredService<IQueueProcessor>();
processor.ProcessNextBatchAsync(stoppingToken);
}
(Exception ex) (ex OperationCanceledException)
{
logger.LogError(ex, );
}
Task.Delay(TimeSpan.FromSeconds(), stoppingToken);
}
}
}
builder.Services.AddHostedService<QueueProcessorWorker>();
```text
```
{
{
scope = scopeFactory.CreateScope();
db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
db.Database.MigrateAsync(cancellationToken);
logger.LogInformation();
}
=> Task.CompletedTask;
}
builder.Services.AddHostedService<DatabaseMigrationService>();
```text
- Always use `IServiceScopeFactory` to create scopes -- hosted services are singletons
- Never inject services directly hosted service constructors
- Handle exceptions inside `ExecuteAsync` --
{
{
services.AddScoped<IOrderRepository, SqlOrderRepository>();
services.AddScoped<IOrderService, OrderService>();
services.AddHostedService<OrderProcessorWorker>();
services;
}
{
services.AddScoped<INotifier, EmailNotifier>();
services.AddScoped<INotifier, SmsNotifier>();
services;
}
}
builder.Services.AddOrderServices();
builder.Services.AddNotificationServices();
```csharp
---
```csharp
[]
{
services = ServiceCollection();
services.AddScoped<IOrderRepository, InMemoryOrderRepository>();
services.AddScoped<IOrderService, OrderService>();
services.AddLogging();
provider = services.BuildServiceProvider();
scope = provider.CreateScope();
service = scope.ServiceProvider.GetRequiredService<IOrderService>();
order = service.GetByIdAsync();
Assert.NotNull(order);
}
```text
For unit tests, prefer direct constructor injection mocks rather than building a full container.
---
**Primary approach:** Use Serena symbol operations efficient code navigation:
**Find definitions**: `serena_find_symbol` instead of text search
**Understand structure**: `serena_get_symbols_overview` organization
**Track references**: `serena_find_referencing_symbols` impact analysis
**Precise edits**: `serena_replace_symbol_body` clean modifications
**When to use Serena vs traditional tools:**
- ✅ **Use Serena**: Navigation, refactoring, dependency analysis, precise edits
- ✅ **Use Read/Grep**: Reading full files, pattern matching, simple text operations
- ✅ **Fallback**: If Serena unavailable, traditional tools work fine
**Example workflow:**
```text
Read: src/Services/OrderService.cs
Grep:
serena_find_symbol:
serena_get_symbols_overview:
```
- [Dependency injection .NET](https:
- [Keyed services .NET ](https:
- [Background tasks hosted services](https:
- [Service lifetimes](https:
- [.NET Framework Design Guidelines](https: