C#9レコードをIOptionsとして使用できますか?

Nov 21 2020

私はC#9と.NET 5.0、特に新しいrecord構成をいじり始めたところです。レコードタイプの簡略構文の優れたユースケースがたくさんあることがわかりました。

私が検討したユースケースの1つは、ASP.NET Coreアプリケーションに対して、通常のクラスrecordIOptions<>はなく、のdtoにを使用することでした。これらのオプションクラスは通常非常に単純なので、完全に適合すると思いましたが、を使用してアプリケーションを構成IOptions<>するにはオブジェクトにパラメーターのないコンストラクターが必要なため、簡単に機能させることができないようです。

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

上記の例では、IOption<>.Valueプロパティにアクセスしようとすると、次の例外がスローされます。

System.MissingMethodException: 'タイプ' AcmeSolution.MyOptions 'に対してパラメーターなしのコンストラクターが定義されていません。

IOptionsパラメーターなしのコンストラクターを必要とせずに、レコードのコンストラクターを使用してオプションを逆シリアル化するように構成システムを構成する方法はありますか?

レコードに長い構文を使用することもできますが、クラスを使用するよりも実際にはメリットはありません。

回答

9 Blindy Nov 20 2020 at 23:28

パラメータなしのコンストラクタを必要とせずに、レコードのコンストラクタを使用してオプションを逆シリアル化するようにIOptions構成システムを構成する方法はありますか?

いいえ、一般にASP.Net Coreは多くのランタイム型インスタンス化を使用します。これには、事前にわかっているコンストラクター呼び出しが必要です。この場合、引数のないコンストラクターが必要です。

ただし、レコードクラスにパラメーターなしのコンストラクターを持たせることができます。

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

その価値はありますか?ええ あなた次第。パフォーマンスの面では、通常のクラスよりも悪くはないので、より明確なものを選んでください。

編集:あるいは、次のフォームを使用できるはずです:

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