Claude-skill-registry configuring-dependency-injection
Configures Dependency Injection using Microsoft.Extensions.DependencyInjection and GenericHost. Use when setting up DI container, registering services, or implementing IoC patterns in .NET projects.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/configuring-dependency-injection" ~/.claude/skills/majiayu000-claude-skill-registry-configuring-dependency-injection && rm -rf "$T"
manifest:
skills/data/configuring-dependency-injection/SKILL.mdsource content
Dependency Injection and GenericHost Usage
A guide on using Dependency Injection and GenericHost in .NET projects.
Core Principles
- Implement dependency injection using Microsoft.Extensions.DependencyInjection
- Use GenericHost (Microsoft.Extensions.Hosting) as the default
- Apply service injection through Constructor Injection
Console and General Projects - Program.cs
// Program.cs using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; // Configure DI using GenericHost var host = Host.CreateDefaultBuilder(args) .ConfigureServices((context, services) => { // Register services services.AddSingleton<IUserRepository, UserRepository>(); services.AddScoped<IUserService, UserService>(); services.AddTransient<IEmailService, EmailService>(); // Register main application service services.AddSingleton<App>(); }) .Build(); // Get service through ServiceProvider var app = host.Services.GetRequiredService<App>(); await app.RunAsync(); // Application class - Constructor Injection public sealed class App(IUserService userService, IEmailService emailService) { private readonly IUserService _userService = userService; private readonly IEmailService _emailService = emailService; public async Task RunAsync() { // Use injected services var users = await _userService.GetAllUsersAsync(); foreach (var user in users) { await _emailService.SendWelcomeEmailAsync(user.Email); } } }
WPF Project - App.xaml.cs
// App.xaml.cs namespace MyApp; using System.Windows; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; public partial class App : Application { private readonly IHost _host; public App() { // Create GenericHost and register services _host = Host.CreateDefaultBuilder() .ConfigureServices((context, services) => { // Register services services.AddSingleton<IUserRepository, UserRepository>(); services.AddSingleton<IUserService, UserService>(); services.AddTransient<IDialogService, DialogService>(); // Register ViewModels services.AddTransient<MainViewModel>(); services.AddTransient<SettingsViewModel>(); // Register Views services.AddSingleton<MainWindow>(); }) .Build(); } protected override async void OnStartup(StartupEventArgs e) { await _host.StartAsync(); // Get MainWindow from ServiceProvider var mainWindow = _host.Services.GetRequiredService<MainWindow>(); mainWindow.Show(); base.OnStartup(e); } protected override async void OnExit(ExitEventArgs e) { using (_host) { await _host.StopAsync(); } base.OnExit(e); } }
MainWindow.xaml.cs - Constructor Injection
// MainWindow.xaml.cs namespace MyApp; using System.Windows; public partial class MainWindow : Window { // ViewModel injection through Constructor Injection public MainWindow(MainViewModel viewModel) { InitializeComponent(); DataContext = viewModel; } }
ViewModel - Constructor Injection
// ViewModels/MainViewModel.cs namespace MyApp.ViewModels; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; public sealed partial class MainViewModel : ObservableObject { private readonly IUserService _userService; private readonly IDialogService _dialogService; // Constructor Injection public MainViewModel(IUserService userService, IDialogService dialogService) { _userService = userService; _dialogService = dialogService; LoadDataAsync(); } [ObservableProperty] private ObservableCollection<User> _users = []; [RelayCommand] private async Task LoadDataAsync() { try { var userList = await _userService.GetAllUsersAsync(); Users = new ObservableCollection<User>(userList); } catch (Exception ex) { await _dialogService.ShowErrorAsync("Error occurred", ex.Message); } } }
Service Lifetime Rules
Singleton
Creates only one instance throughout the application
- Repository, global state management services
services.AddSingleton<IUserRepository, UserRepository>()
Scoped
Creates one instance per request (Scope)
- DbContext, transaction-based services
services.AddScoped<IUserService, UserService>()- ⚠️ Generally not used in WPF (mainly used in Web applications)
Transient
Creates a new instance on every request
- ViewModel, one-time services
services.AddTransient<MainViewModel>()
Direct Use of ServiceProvider (Not Recommended)
Anti-pattern: Service Locator
// Service Locator pattern (anti-pattern) public sealed class SomeClass { private readonly IServiceProvider _serviceProvider; public SomeClass(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public void DoSomething() { // ⚠️ Not recommended: Using ServiceProvider directly var service = _serviceProvider.GetRequiredService<IUserService>(); } }
Recommended: Constructor Injection
// Correct way: Use Constructor Injection public sealed class SomeClass { private readonly IUserService _userService; public SomeClass(IUserService userService) { _userService = userService; } public void DoSomething() { // ✅ Recommended: Use service injected through Constructor Injection _userService.GetAllUsersAsync(); } }
Required NuGet Packages
<ItemGroup> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" /> </ItemGroup>