【问题标题】:Configuration binding exception in array not catched?未捕获数组中的配置绑定异常?
【发布时间】:2020-07-30 09:45:35
【问题描述】:

配置中数组的异常没有通过?!对于一维配置,这是有效的(如您所见here)。但是,当使用更多维度配置时,将忽略异常,如下例所示:

appsettings.json

{
  "Value": 1,
  "ArrayValue": [
    { "Value":  0 }
  ]
}

Config.cs

class Config
{
  private int value;

  public int Value
  {
    get => this.value;
    set
    {
        if (value < 1)
            throw new NullReferenceException();     // ExceptionType only for testing purpose

        this.value = value;
    }
  }

  public IEnumerable<ConfigArray> ArrayValue { get; set; }
}

class ConfigArray
{
  private int arrayValue;

  public int ArrayValue
  {
    get => this.arrayValue;
    set
    {
        if (value < 1)
            throw new NullReferenceException();     // ExceptionType only for testing purpose

        this.arrayValue = value;
    }
  }
}

程序 sn-p

Config config;

try
{
    IConfigurationRoot configuration = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", false, false)
        .Build();

    config = configuration.Get<Config>();
    //config = new Config();
    //configuration.Bind(config);
}
catch (Exception ex)
{
    Console.WriteLine($"Exception: {ex.Message}");
}

<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.6" />

ConfigArray 中的异常没有绕过到主程序。我是否遗漏了某些内容或数组中的异常通常被配置绑定器忽略?

【问题讨论】:

    标签: c# exception .net-core configuration


    【解决方案1】:

    我找到的一个可能的解决方案是创建一个属性来确定是否发生错误。

    可能的解决方案:

    Config.cs

    // If more than one error is possible, it can be a better solution to generate error codes
    enum ErrorCode
    {
      OK,
      ERROR
    }
    
    class Config
    {
      private int value;
      private IEnumerable<ConfigArray> configArray;
    
      public int Value
      {
        get => this.value;
        set
        {
          if (value < 1)
            throw new NullReferenceException();     // ExceptionType only for testing purpose
    
          this.value = value;
        }
      }
    
    
      public IEnumerable<ConfigArray> ArrayValue
      {
        get => this.configArray;
        set
        {
          value.ToList().ForEach(c =>
          {
            switch (c.Error)
            {
              case ErrorCode.ERROR:
                throw new NullReferenceException();
              default:
                break;
            }   
          });
    
          this.configArray = value;
        }
      }
    }
    
    class ConfigArray
    {
      private int arrayValue;
    
      public int ArrayValue
      {
        get => this.arrayValue;
        set
        {
          this.Error = ErrorCode.OK;
    
          if (value < 1)
            this.Error = ErrorCode.ERROR;
    
          this.arrayValue = value;
        }
      }
    
      public ErrorCode Error { get; private set; }
    }
    

    程序片段

    Config config = null;
    
    try
    {
      IConfigurationRoot configuration = new ConfigurationBuilder()
          .SetBasePath(Directory.GetCurrentDirectory())
          .AddJsonFile("appsettings.json", false, false)
          .Build();
    
      config = configuration.Get<Config>();
      //config = new Config();
      //configuration.Bind(config);
    }
    catch (Exception ex)
    {
      if(ex.InnerException is Exception)
          Console.WriteLine($"Inner Exception: {ex.InnerException.Message}");
    
      Console.WriteLine($"Exception: {ex.Message}");
    }
    

    也许有更好的解决方案?

    【讨论】:

      【解决方案2】:

      请参阅此处了解更多信息。 Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs

      private static Array BindArray(Array source, IConfiguration config, BinderOptions options)
      {
          IConfigurationSection[] children = config.GetChildren().ToArray();
          int arrayLength = source.Length;
          Type elementType = source.GetType().GetElementType();
          var newArray = Array.CreateInstance(elementType, arrayLength + children.Length);
      
          // binding to array has to preserve already initialized arrays with values
          if (arrayLength > 0)
          {
              Array.Copy(source, newArray, arrayLength);
          }
      
          for (int i = 0; i < children.Length; i++)
          {
              try
              {
                  object item = BindInstance(
                      type: elementType,
                      instance: null,
                      config: children[i],
                      options: options);
                      
                  if (item != null)
                  {
                      newArray.SetValue(item, arrayLength + i);
                  }
              }
              catch
              {
              }
          }
      
          return newArray;
      }
      

      如您在上面的代码中所见,我们捕获并处理异常。 因此,有必要像sunriax那样采取行动。

      【讨论】:

        猜你喜欢
        • 2019-11-20
        • 1970-01-01
        • 1970-01-01
        • 2015-01-07
        • 2017-05-10
        • 1970-01-01
        • 1970-01-01
        • 2017-05-24
        • 1970-01-01
        相关资源
        最近更新 更多