.NET应用配置对象注入:SimpleInjector获取IConfiguration最佳方案
Great question! Ditching that static container wrapper is absolutely the right call—static service locators are an anti-pattern that hides dependencies, hurts testability, and makes your code harder to maintain. Let’s walk through the cleanest, most maintainable solution to refactor your Linq2Db settings class with proper dependency injection using SimpleInjector and IConfiguration.
Step 1: Refactor Linq2DbSettings to use constructor injection
Instead of reaching for a static container, we’ll explicitly inject IConfiguration into your settings class via its constructor. This makes the class’s dependencies clear, and lets SimpleInjector handle resolving them automatically.
Here’s the updated code:
using Microsoft.Extensions.Configuration; using LinqToDB.Configuration; public class Linq2DbSettings : ILinqToDBSettings { private readonly IConfiguration _configuration; // Inject IConfiguration directly via constructor—no static containers needed! public Linq2DbSettings(IConfiguration configuration) { _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); } public IEnumerable<IDataProviderSettings> DataProviders { get { yield break; } } public string DefaultConfiguration => "SqlServer"; public string DefaultDataProvider => ProviderName.SqlServer; public IEnumerable<IConnectionStringSettings> ConnectionStrings { get { yield return new ConnectionStringSettings { Name = "SqlServer", ProviderName = "SqlServer", // Pull the connection string from IConfiguration (works with appsettings.json, environment vars, etc.) ConnectionString = _configuration.GetConnectionString("Default") }; } } } // Your existing ConnectionStringSettings class stays the same public class ConnectionStringSettings : IConnectionStringSettings { public string ConnectionString { get; set; } public string Name { get; set; } public string ProviderName { get; set; } public bool IsGlobal => false; }
Step 2: Register your settings with SimpleInjector
Since you already have IConfiguration registered in your SimpleInjector container, all you need to do is register ILinqToDBSettings to resolve to your Linq2DbSettings class. Add this to your container configuration code:
// Register as a singleton since settings don't change at runtime container.Register<ILinqToDBSettings, Linq2DbSettings>(Lifestyle.Singleton);
Step 3: Bonus: Use strongly-typed configuration (optional but recommended)
For even better maintainability, you can bind your Linq2Db settings to a strongly-typed class instead of accessing IConfiguration directly. This makes your configuration easier to validate and refactor.
- First, add a config section to your
appsettings.json(or config source):
{ "Linq2Db": { "DefaultConfiguration": "SqlServer", "DefaultDataProvider": "SqlServer", "ConnectionStrings": [ { "Name": "SqlServer", "ProviderName": "SqlServer", "ConnectionString": "Your_Connection_String_Here" } ] } }
- Create a strongly-typed config class:
public class Linq2DbConfig { public string DefaultConfiguration { get; set; } public string DefaultDataProvider { get; set; } public List<ConnectionStringSettings> ConnectionStrings { get; set; } }
- Update
Linq2DbSettingsto use this class:
public class Linq2DbSettings : ILinqToDBSettings { private readonly Linq2DbConfig _config; public Linq2DbSettings(Linq2DbConfig config) { _config = config ?? throw new ArgumentNullException(nameof(config)); } public IEnumerable<IDataProviderSettings> DataProviders { get { yield break; } } public string DefaultConfiguration => _config.DefaultConfiguration; public string DefaultDataProvider => _config.DefaultDataProvider; public IEnumerable<IConnectionStringSettings> ConnectionStrings => _config.ConnectionStrings; }
- Bind the config section and register it in SimpleInjector:
// Bind the config section to our strongly-typed class var linq2DbConfig = configuration.GetSection("Linq2Db").Get<Linq2DbConfig>(); container.RegisterInstance(linq2DbConfig); // Register the settings class as before container.Register<ILinqToDBSettings, Linq2DbSettings>(Lifestyle.Singleton);
Why this works (and why it’s better than static containers)
- Clear dependencies: Your
Linq2DbSettingsclass explicitly declares what it needs to work, making your code easier to read and debug. - Testability: You can easily mock
IConfigurationor your strongly-typedLinq2DbConfigfor unit tests, without needing to spin up a full container. - Follows SOLID principles: This adheres to the Dependency Inversion Principle, keeping your settings class decoupled from configuration implementation details.
- No hidden dependencies: Static containers hide where dependencies come from—constructor injection makes everything transparent.
内容的提问来源于stack exchange,提问作者advapi

