Заставляет IConfigurationBuilder.Bind () выдавать ошибку, когда не удается привязать объект - PullRequest
0 голосов
/ 09 октября 2019

У меня есть консольное приложение, в котором я пытаюсь связать раздел конфигурации в список пользовательских типов объектов, например:

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 голосов
/ 09 октября 2019

На основе этой записи :

Система конфигурации 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 () выдает исключение, если есть проблема с вашей конфигурацией и привязкой.

0 голосов
/ 09 октября 2019

Перед привязкой объекта проверьте объект «Вручную».

Сначала просматривайте значения конфигурации в виде строки. Посмотрите, соответствуют ли они существующему элементу в перечислении. Использование функции 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.");
             }
         }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...