Tl; dr: Мне нужен класс параметров, который использует ненулевые типы для своих элементов без значений по умолчанию.
C# 8.0 представляет Обнуляемые ссылочные типы.
Я обнаружил, что использование обнуляемых ссылочных типов с шаблоном ASP. Net параметров довольно сложно, неполно или я что-то упускаю. Я испытываю ту же проблему, описанную в этом стеке над сообщением о потоке .
- Мы не хотим делать Name обнуляемым, поскольку тогда нам нужно разместить традиционные проверки на ноль везде (что противоречит назначению необнуляемых ссылочных типов)
- Мы не можем создать конструктор для принудительного создания класса MyOptions с ненулевым значением имени, так как метод Configure создает экземпляр параметров для нас
- Мы не можем использовать уловку прощающего оператора (publi c string name {get; set;} = null !;), так как тогда мы не можем гарантировать, что свойство Name установлено и мы можем в конечном итоге получить нулевое значение в свойстве Name, где этого не следует ожидать (внутри служб)
Я хочу класс параметров, который использует ненулевые типы для своих члены без значений по умолчанию. Ответы в этом посте заканчиваются тем, что в любом случае используются обнуляемые типы (которых я пытаюсь избежать) или значения по умолчанию (которых я также пытаюсь избежать).
Комментарии a но проверка параметров выявляет хорошие моменты и выглядит многообещающе, но оказывается, что для метода Validate
все еще нужен объект параметров для проверки, который побеждает цель, если вам уже нужно передать объект параметров в it.
public ValidateOptionsResult Validate(string name, MyOptions options)
// Pointless if MyOptions options is being passed in here
Это бессмысленно, потому что я определил, что единственный способ принудительного применения класса параметров со всеми ненулевыми членами и без значений по умолчанию - иметь конструктор. Возьмите, например, приведенный ниже пример кода.
namespace SenderServer.Options
{
using System;
using Microsoft.Extensions.Configuration;
/// <summary>
/// Configuration options for json web tokens.
/// </summary>
public class JwtOptions
{
/// <summary>
/// The secret used for signing the tokens.
/// </summary>
public String Secret { get; }
/// <summary>
/// The length of time in minutes tokens should last for.
/// </summary>
public Int32 TokenExpirationInMinutes { get; }
/// <summary>
/// Configuration options for json web tokens.
/// </summary>
/// <param name="secret"> The secret used for signing the tokens.</param>
/// <param name="tokenExpirationInMinutes">The length of time in minutes tokens should last for.</param>
public JwtOptions(String secret, Int32 tokenExpirationInMinutes)
{
Secret = secret;
TokenExpirationInMinutes = tokenExpirationInMinutes;
}
/// <summary>
/// Create a JwtOptions instance from a configuration section.
/// </summary>
/// <param name="jwtConfiguration">The configuration section.</param>
/// <returns>A validated JwtOptions instance.</returns>
public static JwtOptions FromConfiguration(IConfiguration jwtConfiguration)
{
// Validate the secret
String? secret = jwtConfiguration[nameof(Secret)];
if (secret == null)
{
throw new ArgumentNullException(nameof(Secret));
}
// Validate the expiration length
if (!Int32.TryParse(jwtConfiguration[nameof(TokenExpirationInMinutes)], out Int32 tokenExpirationInMinutes))
{
throw new ArgumentNullException(nameof(TokenExpirationInMinutes));
}
if (tokenExpirationInMinutes < 0)
{
throw new ArgumentOutOfRangeException(nameof(TokenExpirationInMinutes));
}
return new JwtOptions(secret, tokenExpirationInMinutes);
}
}
}
Так что, если мне понадобится конструктор с параметрами для класса, то я могу создать его самостоятельно с чем-то вроде:
// Configure the JWT options
IConfiguration jwtConfiguration = Configuration.GetSection("Authentication:JwtOptions");
JwtOptions jwtOptions = JwtOptions.FromConfiguration(jwtConfiguration); // This performs validation as well
но тогда куда мне положить jwtOptions
? Ни один из services.Configure<JwtOptions>(jwtOptions);
и вариантов просто не принимает уже созданный экземпляр объекта (или, по крайней мере, ни один из тех, что я видел). И, наконец, даже если они это сделали, вы не можете использовать класс опций с внедрением зависимостей, который не имеет общедоступного c конструктора без параметров.
public JwtService(IOptions<JwtOptions> jwtOptions)