Skip to content

Add a fluent Validate overload for adding validator types#127264

Open
89netraM wants to merge 2 commits intodotnet:mainfrom
89netraM:feature/options-builder-validator-type
Open

Add a fluent Validate overload for adding validator types#127264
89netraM wants to merge 2 commits intodotnet:mainfrom
89netraM:feature/options-builder-validator-type

Conversation

@89netraM
Copy link
Copy Markdown

Adds a Validate overload to the OptionsBuilder that registers an IValidateOptions type that validates the option type.

Closes #115200

Adds a Validate overload to the OptionsBuilder that registers an
IValidateOptions type that validates the option type.
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Apr 22, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-extensions-options
See info in area-owners.md if you want to be subscribed.

@cincuranet cincuranet self-assigned this Apr 22, 2026
/// </summary>
/// <typeparam name="TValidateOptions">The validation type.</typeparam>
/// <returns>The current <see cref="OptionsBuilder{TOptions}"/>.</returns>
public virtual OptionsBuilder<TOptions> Validate<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TValidateOptions>()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing Func<>-based Validate overloads pass Name to ValidateOptions, so validation is scoped to the OptionsBuilder's named option:

 // Only validates option named "A"
 services.AddOptions<MyOpts>("A").Validate(o => o.X > 0);

The new Validate() registers the type directly; the validator sees all option names, not just the one on this builder. Whether it filters by name is entirely up to TValidateOptions. This is inherent to the IValidateOptions<T> interface design, but it's a behavioral difference users might not expect from a method sitting alongside the name-scoped overloads.

Assert.NotNull(value);
}

[Fact]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a couple more test cases?

  1. Validator with constructor-injected dependencies; this is the key scenario the API enables (e.g., [OptionsValidator]-generated types) and would exercise the DynamicallyAccessedMembers(PublicConstructors) annotation. Something like a validator that takes an ILogger or a custom service in its constructor.

  2. Named options; verify behavior when the OptionsBuilder is configured with a non-default name (e.g., AddOptions<ComplexOptions>("myName")). Since unlike the Func<>-based Validate overloads, this method doesn't scope to the builder's Name, it would be good to have a test that documents this behavior explicitly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-Extensions-Options community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API Proposal]: Add a fluent OptionsBuilder method that adds validator types

4 participants