【问题标题】:Bind IConfiguration to C# Record Type将 IConfiguration 绑定到 C# 记录类型
【发布时间】:2021-04-27 18:19:48
【问题描述】:

我想将配置绑定到记录类型。

这是配置类型的定义(没有无参构造函数):

public record AppConfiguration(string ConnectionString);

这是示例Main 方法:

public static void Main(string[] args)
{
    var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
    AppConfiguration appConfig = new(); // error
    configuration.GetSection("app").Bind(appConfig);
}

如果我将定义转换为:

public record AppConfiguration
{
    public string ConnectionString {get; init;}
}

它按预期工作,但我宁愿使用记录的“单行”定义。 记录是否适合此用例?

【问题讨论】:

    标签: c# configuration c#-record-type


    【解决方案1】:

    您的第一种方法的问题在于,使用单行声明您已经自动定义了primary constructor,它

    导致隐式声明的默认类构造函数,如果存在, 被压制。

    在第二种情况下,主构造函数是无参数构造函数,因此它按预期工作。只是为了澄清任何疑问,init 访问器是向后兼容的,所以即使 ConnectionString 没有直接初始化,它也会取值 null。我猜Bind 方法会使用反射正确填充它。

    【讨论】:

      【解决方案2】:

      我通过在单行语法中使 ConnectionString 可以为空,并使用空值启动记录来解决它:

      public record AppConfiguration(string? ConnectionString);
      

      主要:

      public static void Main(string[] args)
      {
          var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
          AppConfiguration appConfig = new(null);
          configuration.GetSection("app").Bind(appConfig);
      }
      

      注意:

      我对这个实现有些担心,因为它没有表达正确的意图;即,ConnectionString 可以为空是可以的。虽然我可以在编写代码时通过引发空值异常来处理此问题,但如果其他人稍后使用它,可能会导致混乱。

      默认情况下,我建议坚持使用传统方法,直到发布更好的解决方案。

      【讨论】:

        【解决方案3】:

        我创建了一个很小的NuGet package 来处理绑定配置到位置记录或没有无参数构造函数的类。

        如果你引用包,那么你只需要一行:

        configuration.Bind<AppConfiguration>();
        

        如果您的配置文件部分与类型名称不匹配,那么您可以传递部分名称:

        configuration.Bind<AppConfiguration>("app");
        

        【讨论】:

          猜你喜欢
          • 2015-05-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-08-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多