为ASP.NET Core中的选项自定义JSON属性名称

Ond*_*cik 9 c# asp.net-core

从JSON文件加载配置时,我想使用其他属性名称进行配置。

public class MinioConfiguration
{
    [DataMember(Name = "MINIO_ENDPOINT")]
    public string Endpoint { get; set; }
    [DataMember(Name = "MINIO_ACCESS_KEY")]
    public string AccessKey { get; set; }
    [DataMember(Name = "MINIO_SECRET_KEY")]
    public string SecretKey { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

既不DataMember也不JsonProperty工作。有可能实现吗?

小智 38

现在可以使用ConfigurationKeyNameAttribute.NET 6 Preview 4 中提供的 来实现这一点。请查看此处以了解更多详细信息。例如:

public class MinioConfiguration
{
    [ConfigurationKeyName("MINIO_ENDPOINT")]
    public string Endpoint { get; set; }
    [ConfigurationKeyName("MINIO_ACCESS_KEY")]
    public string AccessKey { get; set; }
    [ConfigurationKeyName("MINIO_SECRET_KEY")]
    public string SecretKey { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

  • 伟大的 !!它应该被标记为已接受的答案 (2认同)

pok*_*oke 6

不幸的是,这是不可能的。这里负责的组件是JSON配置提供程序(Microsoft.Extensions.Configuration.Json)和配置绑定程序(Microsoft.Extensions.Configuration.Binder)。前者负责将JSON文件加载到中IConfiguration,而后者的工作是将an映射IConfiguration到类型中。

但是,配置绑定器与源无关,因此它并不关心配置来自何处,无论是JSON,内存中配置还是环境变量。因此,根据设计,活页夹无法在目标类型上查找特定于源的属性。

另一方面,不能保证将配置绑定到任何类型,因此无论配置提供程序是否绑定到类型,它都需要一致地工作。因此,JSON提供程序遵循其自己的约定将JSON属性映射到配置键。

由于这两个组件都是独立运行的(活页夹甚至在IConfiguration对象上显式运行,因此它的运行要比实际配置解析过程晚得多),因此它们无法通信和共享信息。因此,JSON配置提供程序完全不可能访问该信息,而绑定器会在以后获取有关目标类型的信息。因此,您根本无法更改配置名称。

但是,我认为无论如何都不应该这样做。配置是非常特定于应用程序的事情,但是如果您想使用看起来像是要使用应用程序不一定拥有的配置文件的其他密钥。我建议不要使用这种方法,而应使用特定于应用程序的配置文件。

如果需要重用该配置文件,则始终可以为该特定类型编写自己的配置提供程序。编写配置提供程序并不困难,特别是当您要将其限制为非常特定的格式时。

  • 如果我们在谈论配置文件,我同意你的论点。但我正在使用环境变量中的配置变量 - Docker ENV 变量。它们是在容器启动期间配置的,在这种情况下映射某些配置文件没有意义。环境变量是例如`S3_ENDPOINT`、`S3_ACCESS_KEY`、`SQL_ENDPOINT`。在应用程序中,它的定义有点不同,`S3Configuration { Endpoint {get;set; } 和 SqlConfiguration { 端点 {get; 设置;}}`。为了实现这种干净的分离,这是需要的。 (2认同)

Vei*_*edo 6

万一有人碰到这个。

这是老办法:

  public class ServiceConfig
  {
    private string web_internal
    {
      // Note it does not work without this noop getter
      get => "it's hack for Microsoft.Configuration.Binder";
      set => WebInternal = value;
    }

    public string WebInternal { get; set; }
  }
Run Code Online (Sandbox Code Playgroud)

然后在您想要绑定它的地方

var serviceConfig = config.Get<ServiceConfig>(o => o.BindNonPublicProperties = true);
Run Code Online (Sandbox Code Playgroud)

尽管我认为Microsoft应该添加支持以覆盖名称。

这与与ConfigurationSource的关系无关,而与ConfigurationBinder本身有关-如果它看到该属性具有DataMember属性,则应使用该属性代替键的属性名称。