Background and motivation
Since the introduction of compile-time generated options validators that are NativeAOT compatible, more developers will want to add this kind of validator instead of the reflection-based validators. Adding the reflection-based validator is easy with a fluent OptionsBuilder method, but adding a "user defined" (either implemented by a user or compile-time generated) requires manually adding the validator to the service collection.
I propose a new overload to the Validate method on OptionsBuilder that provides a fluent way of adding validator types for validating an option. Introducing this method would not only make users code more concise but make the way of adding validators more discoverable, since the OptionsBuilder is already the place where most users add validation (often via the ValidateDataAnnotations method).
API Proposal (edited by @cincuranet)
namespace Microsoft.Extensions.Options;
public class OptionsBuilder<TOptions> where TOptions : class
{
public virtual OptionsBuilder<TOptions> ValidateWith<TValidateOptions>() where TValidateOptions : class, IValidateOptions<TOptions>;
}
I've made the method virtual because most other methods in OptionsBuilder are. But I don't see the need for it.
API Usage
It would be used in a similar way to how the Validate(Func<TOptions, bool> validation) or ValidateDataAnnotations() for example are used.
services.AddOptions<MyOption>()
.ValidateWith<MyOptionValidator>();
class MyOption
{
[Required]
public required string Config { get; set; }
}
[OptionsValidator]
partial class MyOptionValidator : IValidateOptions<MyOption>;
Alternative Designs (edited by @cincuranet)
Another good name is AddValidator. We don't think adding overload to Validate is pit-of-success.
The same thing can already be achieved with this (slightly more verbose) code snippet, and the new method might not be necessary.
services.AddOptions<MyOption>();
services.AddTransient<IValidateOptions<MyOption>, MyOptionValidator>();
class MyOption
{
[Required]
public required string Config { get; set; }
}
[OptionsValidator]
partial class MyOptionValidator : IValidateOptions<MyOption>;
Risks
Increased API surface.
Background and motivation
Since the introduction of compile-time generated options validators that are NativeAOT compatible, more developers will want to add this kind of validator instead of the reflection-based validators. Adding the reflection-based validator is easy with a fluent
OptionsBuildermethod, but adding a "user defined" (either implemented by a user or compile-time generated) requires manually adding the validator to the service collection.I propose a new overload to the
Validatemethod onOptionsBuilderthat provides a fluent way of adding validator types for validating an option. Introducing this method would not only make users code more concise but make the way of adding validators more discoverable, since theOptionsBuilderis already the place where most users add validation (often via theValidateDataAnnotationsmethod).API Proposal (edited by @cincuranet)
I've made the method
virtualbecause most other methods inOptionsBuilderare. But I don't see the need for it.API Usage
It would be used in a similar way to how the
Validate(Func<TOptions, bool> validation)orValidateDataAnnotations()for example are used.Alternative Designs (edited by @cincuranet)
Another good name is
AddValidator. We don't think adding overload toValidateis pit-of-success.The same thing can already be achieved with this (slightly more verbose) code snippet, and the new method might not be necessary.
Risks
Increased API surface.