繁体   English   中英

如何将单个 IOptions POCO 交叉绑定到多个配置提供程序?

[英]How to cross-bind single IOptions POCO to multiple configuration providers?

我是 .net 内核的新手,我在为单个 POCO 使用多个配置提供程序时遇到问题。 我使用的是 .net 内核,而不是 asp.net 内核。

为了清楚起见,我试图简化类,请忽略任何编译错误。 我的配置的model如下:

public class Configurations
{
  public EnvironmentConfig EnvironmentConfig {get; set;}
  public ServerConfig ServerConfig {get; set;}
}

public class EnvironmentConfig
{
  public string EnvironmentStr {get; set;}
}

public class ServerConfig
{
  public string Address {get; set;}
  public string Username {get; set;}
  public string Password {get; set;}
}

我有两个提供程序 - appsettings.json和一个数据库。 该数据库与其他服务一起使用,因此无法轻松更改数据(可以认为是只读的)。 appsettings.json文件具有以下层次结构:

{
  "EnvironmentConfig": {
    "EnvironmentStr": "dev"
  },
  "ServerConfig": {
    "Address": "https://example.com"
    // the other properties are not here, they're kept only in the database
  }
}

数据库没有层次结构,只提供缺失的属性(我将再次使用 JSON 以保持一致性):

{
  "Username": "user"
  "Password": "password"
}

当我尝试获取IOptionsMonitor<Configurations> object 时,仅在ServerConfig中填充了Address属性,就像它仅从appsettings.json读取一样(用户名和密码位于根级别,因此未正确绑定它们):

var configs = host.Services.GetService<IOptionsMonitor<Configurations>>().CurrentValue;

{
  "EnvironmentConfig": {
    "EnvironmentStr": "dev"
  },
  "ServerConfig": {
    "Address": "https://example.com"
    "Username": null,
    "Password": null
  }
}

当我尝试获取IOptionsMonitor<ServerConfig> object 时,它只绑定数据库中的数据:

var serverConfig = host.Services.GetService<IOptionsMonitor<ServerConfig>>().CurrentValue;

{
  "Address": null,
  "Username": "user",
  "Password": "password"
}

看起来我没有正确绑定它。 我尝试了多种方法,但没有奏效:

public static IServiceCollection AddConfiguration(this IServiceCollection services, IConfiguration configuration)
{
  services
    .Configure<ServerConfig>(configuration) // the db properties are also at root level
    .Configure<Configurations>(configuration);
  return serviceCollection;
}
public static IServiceCollection AddConfiguration(this IServiceCollection services, IConfiguration configuration)
{
  services
    .AddOptions<ServerConfig>()
    .Bind(configuration.GetSection("ServerConfig");
  services
    .AddOptions<Configurations>()
    .Bind(configuration);
  return serviceCollection;
}

有人可以解释如何正确绑定它,而不管层次结构的差异如何,因此ServerConfigConfigurations中填充了所有属性?

我假设数据库作为自定义配置提供程序访问

更新来自数据库的键以匹配所需的层次结构

数据库

"ServerConfig:Username" -> "user"
"ServerConfig:Password" -> "password"

所以配置框架在合并来自多个配置提供程序的所有配置时知道您指的是什么。

在加载配置时,从数据库中提取设置并将层次结构添加到键中。

简化示例:

public class ServerConfigProvider : ConfigurationProvider {
    public ServerConfigProvider (Action<DbContextOptionsBuilder> optionsAction) {
        OptionsAction = optionsAction;
    }

    Action<DbContextOptionsBuilder> OptionsAction { get; }

    public override void Load() {
        var builder = new DbContextOptionsBuilder<MyEFConfigurationContext>();

        OptionsAction(builder);

        using (var dbContext = new MyEFConfigurationContext(builder.Options)) {
            Data = dbContext.MySettingsTable.ToDictionary(c => $"ServerConfig:{c.Key}", c => c.Value);
        }
    }    
}

参考自定义配置提供程序

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM