![](/img/trans.png)
[英]Unable to read/bind configuration settings with strongly-typed class using Named Options in Asp.Net Core 3
[英]Accessing strongly typed configuration settings directly into class library in ASP.NET 5 (vNext)?
我有一个ASP.NET 5 MVC 6应用程序。 它具有一个数据访问库,该库需要一个连接字符串来建立与数据库的连接。 目前,我正在将带有连接字符串的强类型配置设置类作为公共属性从MVC控制器(通过DI接收)一直传递到数据访问类库。
我想知道类库是否有更好的方法使用依赖注入或任何其他机制来访问强类型配置设置?
谢谢。
编辑:代码示例
这是从业务层调用的通用DbTransaction类。
public class DbTransactions<TEntity> where TEntity : DbEntity, new()
{
private readonly Query _query;
public DbTransactions(string connectionString)
{
_query = new Query(connectionString);
}
public TEntity GetById(long id)
{
var sqlGenerator = new SqlGenerator<TEntity>();
var sql = sqlGenerator.GetSelectByIdQuery();
var mapper = new NMapper.Mapper<TEntity>();
var cmd = _query.GetNpgsqlCommand(sql, new { id });
return mapper.GetObject(cmd);
}
}
查询类从提供给它的连接字符串创建连接对象。
我同意@Steven的观点,即使用IOptions<T>
是一个坏主意。 但是,您可以使用ConfigurationBinder
扩展将ConfigurationBinder
的特定部分读出到强类型POCO类中。 只需确保在project.json的dependencies
部分中有此设置即可:
"dependencies": {
[other dependencies],
"Microsoft.Extensions.Configuration.Binder": "1.0.0-rc1-final",
[other dependencies]
}
只需像往常一样建立您的配置即可。 例如,假设您有一个如下所示的Database.json配置文件:
{
"Database": {
"ConnectionInfo": {
"connectionString": "myConnectionString"
}
}
}
您可以从Startup.cs中的Startup
方法构建配置:
public IConfiguration Configuration { get; private set; }
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv) {
IConfigurationBuilder configBuilder = new ConfigurationBuilder()
.SetBasePath(appEnv.ApplicationBasePath)
.AddJsonFile("Database.json")
.AddEnvironmentVariables()
Configuration = configBuilder.Build();
}
现在,我们可以创建一个POCO类以匹配JSON配置文件的"Database:ConnectionInfo"
部分。 您可以按照@janhartmann的建议将其与接口匹配,但这可能有必要,也可能没有必要。
public class DatabaseConnectionInfo {
public string ConnectionString { get; set; }
}
现在,我们如何从JSON配置文件中获取填充了DatabaseConnectionInfo
类的数据? 一种方法是使用IOptions<T>
框架类型,但是当我可以避免使用框架类型时,我不喜欢使用它们。 相反,您可以获取如下实例:
DatabaseConnectionInfo dbConnInfo = Configuration
.GetSection("Database:ConnectionInfo")
.Get<DatabaseConnectionInfo>();
现在,您只需注册dbConnInfo
类型为类型的单DatabaseConnectionInfo
(或为接口的单,如果你希望有一个不变的配置设置对象)。 一旦将其注册到IoC容器中,就可以在需要的地方构造函数将其注入:
public class DbTransactions<TEntity> where TEntity : DbEntity, new()
{
private readonly Query _query;
public DbTransactions(DatabaseConnectionInfo dbConnInfo)
{
_query = new Query(dbConnInfo.ConnectionString);
}
public TEntity GetById(long id) { ... }
}
您可以让您的服务类依赖于接口,例如:
public interface IConnectionFactory {
string ConnectionString();
}
public class MyDataAccessClass {
private readonly IConnectionFactory _connectionFactory
public MyDataAccessClass(IConnectionFactory connectionFactory) {
_connectionFactory = connectionFactory;
}
public void Whatever() {
var connectionString = _connectionFactory.ConnectionString();
}
}
然后实现它(尽可能靠近您的合成根):
public class SqlConnectionFactory : IConnectionFactory {
public string ConnectionString() {
return "myConnectionString";
}
}
让接口具有您需要的方法或属性。
电线像:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConnectionFactory, SqlConnectionFactory>();
}
我使用的方法与之前列出的方法类似,但是我认为它的区别足以保证其他答案。
首先,我定义一个具有类所需的所有配置的接口。 在这种情况下
public interface IDbTransactionsConfiguration {
string ConnectionString { get; }
}
然后我更改类以通过构造函数注入进行此配置
public class DbTransactions<TEntity> where TEntity : DbEntity, new() {
public DbTransactions(IDbTransactionsConfiguration configuration) {
...
}
}
然后,我定义一个类来处理我的应用程序的所有配置。
public class MyApplicationConfiguration : IDbTransactionsConfiguration, ISomeOtherConfiguration, etc {
public string ConnectionString { get; }
... other configuration
}
然后,我使用某种依赖注入将这个类传递给所有需要它的类(通常对我来说是Castle Windsor或AutoFac)。
如果由于遗留类型原因而构造DbTransactions
太困难,我定义一个MyApplicationConfiguration的静态版本并直接访问它。
有关此博客文章的更多详细信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.