Posso usar registros C # 9 como IOptions?
Acabei de começar a brincar com C # 9 e .NET 5.0, especificamente a nova recordconstrução. Acho que tenho muitos casos de uso excelentes para a sintaxe abreviada dos tipos de registro.
Um dos casos de uso que considerei foi usar um recordpara o dto em IOptions<>, em vez de classes regulares, para aplicativos ASP.NET Core. Essas classes de opção geralmente são bastante simples, então pensei que seria um ajuste perfeito, mas parece que não consigo fazer funcionar facilmente, pois a configuração do aplicativo usando IOptions<>requer que o objeto tenha um construtor sem parâmetros.
public record MyOptions(string OptionA, int OptionB);
public class Startup
{
public void ConfigureServices(IServiceCollection services) {
services.Configure<MyOptions>(Configuration.GetSection(nameof(MyOptions)));
}
...
}
public class MyController : Controller
{
private readonly MyOptions _options;
public MyController(IOptions<MyOptions> options) {
_options = options.Value; // This throws an exception at runtime
}
}
O exemplo acima lança a seguinte exceção ao tentar acessar a IOption<>.Valuepropriedade:
System.MissingMethodException: 'Nenhum construtor sem parâmetros definido para o tipo' AcmeSolution.MyOptions '.'
Existe alguma maneira de configurar o IOptionssistema de configuração para desserializar as opções usando o construtor do registro em vez de exigir um construtor sem parâmetros?
Eu poderia usar a sintaxe extensa para os registros, mas não há realmente nenhum benefício em usar uma classe.
Respostas
Existe alguma maneira de configurar o sistema de configuração IOptions para desserializar as opções usando o construtor do registro em vez de exigir um construtor sem parâmetros?
Não, em geral o ASP.Net Core usa muitas instâncias do tipo run-time, o que requer chamadas de construtor que são conhecidas de antemão e, neste caso, requer um construtor sem argumentos.
No entanto, você pode fazer com que sua classe de registro tenha um construtor sem parâmetros:
public record MyOptions(string OptionA, int OptionB)
{
public MyOptions(): this(default, default) {}
}
Vale a pena? Eh. Você decide. Não é pior do que uma aula normal, em termos de desempenho, então vá com o que achar mais claro!
Editar: como alternativa, você deve ser capaz de usar este formulário:
public record MyOptions(string OptionA = default, int OptionB = default);