Puis-je utiliser des enregistrements C # 9 comme IOptions?

Nov 21 2020

Je viens de commencer à jouer avec C # 9 et .NET 5.0, en particulier la nouvelle recordconstruction. Je trouve que j'ai beaucoup d'excellents cas d'utilisation pour la syntaxe abrégée des types d'enregistrement.

L'un des cas d'utilisation que j'ai envisagés était d'utiliser un recordpour le dto dans IOptions<>, au lieu de classes régulières, pour les applications ASP.NET Core. Ces classes d'options sont généralement assez simples, donc j'ai pensé que ce serait un ajustement parfait, mais il semble que je ne puisse pas le faire fonctionner facilement, car la configuration de l'application à l'aide de IOptions<>l'objet nécessite un constructeur sans paramètre.

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
    }
}

L'exemple ci-dessus lève l'exception suivante lors de la tentative d'accès à la IOption<>.Valuepropriété:

System.MissingMethodException: 'Aucun constructeur sans paramètre défini pour le type' AcmeSolution.MyOptions '.'

Existe-t-il un moyen de configurer le IOptionssystème de configuration pour désérialiser les options à l'aide du constructeur de l'enregistrement au lieu de nécessiter un constructeur sans paramètre?

Je pourrais utiliser la syntaxe à long terme pour les enregistrements, mais il n'y a vraiment aucun avantage à utiliser une classe.

Réponses

9 Blindy Nov 20 2020 at 23:28

Existe-t-il un moyen de configurer le système de configuration IOptions pour désérialiser les options à l'aide du constructeur de l'enregistrement au lieu de nécessiter un constructeur sans paramètre?

Non, en général, ASP.Net Core utilise beaucoup d'instanciation de type au moment de l'exécution, ce qui nécessite des appels de constructeur connus à l'avance, et dans ce cas, il nécessite un constructeur sans arguments.

Vous pouvez cependant faire en sorte que votre classe d'enregistrement ait un constructeur sans paramètre:

public record MyOptions(string OptionA, int OptionB)
{
    public MyOptions(): this(default, default) {}
}

Est-ce que ça vaut le coup? Eh. À toi de voir. Ce n'est pas pire qu'un cours régulier, en termes de performances, alors allez-y avec ce que vous trouvez plus clair!

Edit: vous devriez également pouvoir utiliser ce formulaire:

public record MyOptions(string OptionA = default, int OptionB = default);