当绑定对象失败时,强制IConfigurationBuilder.Bind()引发错误

时间:2019-10-09 14:42:30

标签: c# config

我有一个控制台应用程序,试图将配置节绑定到这样的自定义对象类型列表中:

List<myObject> myObjectList = new List<myObject>();
config.GetSection("Objects").Bind(myObjectList);
public enum CustomEnum{
     One,
     Two
}

public class myObject{
    public CustomEnum myEnum { get; set; }
}

我的问题是,如果在配置文件中,您没有为该属性提供正确的枚举值(即,如上所示,三个而不是一个或两个),它将无法绑定该对象,并且不会抛出错误告诉您它失败了。所以基本上我该如何做,以至于我知道由于配置值不正确而导致绑定失败?现在,它只是不绑定那些失败的特定对象,这意味着没有真正的方法知道缺少的项目。

成功绑定一个对象但失败并忽略另一个对象的示例配置:

{
   "Objects": [
      {
         "myEnum": "One"
      },
      {
         "myEnum": "Three"
      }
   ]
}

编辑:因此,对于以后发现此问题的任何人以供参考,基本上没有好的解决方案。您只需要手动检查,或者完全不使用配置中的枚举即可。

2 个答案:

答案 0 :(得分:0)

在绑定对象之前验证对象“手动”。

首先以字符串形式遍历配置的值。查看它们是否与枚举中的现有项匹配。使用IsDefined函数。

https://docs.microsoft.com/en-us/dotnet/api/system.enum.isdefined?view=netframework-4.8

如果没有抛出异常。

如果所有项目都在枚举中,请照常使用Bind方法。

    public static bool ValidateConfig(object jsonConfig)
    {
         foreach (string item in jsonConfig) // loop through the config items as string
         {
             if (!Enum.IsDefined(typeof(CustomItem), item))
             {
                  throw new Exception("Enum value does not exist.");
             }
         }
    }

答案 1 :(得分:0)

基于此post

  

ASP.NET Core配置系统非常灵活,可让您   使用强类型设置。但是,部分原因是   灵活性,可能会出现仅配置错误   出现在某些环境中。默认情况下,这些错误只会是   在代码尝试使用无效配置时发现   值(如果有的话)。

     

您可以使用IStartupFilter来验证您的设置,   应用程序启动。这样可以确保您了解配置错误,例如   尽快,而不是在运行时。

因此,首先需要创建一个interface,如下所示:

public interface IValidatable
{
    void Validate();
}

然后:

public class SettingValidationStartupFilter : IStartupFilter
{
    readonly IEnumerable<IValidatable> _validatableObjects;
    public SettingValidationStartupFilter(IEnumerable<IValidatable> validatableObjects)
    {
        _validatableObjects = validatableObjects;
    }

    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    {
        foreach (var validatableObject in _validatableObjects)
        {
            validatableObject.Validate();
        }

        //don't alter the configuration
        return next;
    }
}

然后您需要在DI容器中注册过滤器:

public void ConfigureServices(IServiceCollection services)  
{
    services.AddTransient<IStartupFilter, SettingValidationStartupFilter>()
    // other service configuration
}

最后,您需要在要在启动时验证的设置上实现IValidatable接口:

public class myObject : IValidatable
{
    public CustomEnum myEnum { get; set; }

    public void Validate()
    {
        //Do your validation here
        Validator.ValidateObject(this, new ValidationContext(this), validateAllProperties: true);
    }
}
  

无论使用哪种方法,如果您的配置和绑定存在问题,Validate()方法都会引发异常。