You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
publicinterfaceIMyValidationService{}publicsealedclassMyOptions:IValidatableObject{publicIEnumerable<ValidationResult>Validate(ValidationContextvalidationContext){// This will throw since an IServiceProvider is not available in the ValidationContext_=validationContext.GetRequiredService<IMyValidationService>();return[];}}[OptionsValidator]publicsealedpartialclassMyValidateOptions:IValidateOptions<MyOptions>{}
would generate an options validation implementation that looks like:
partialclassMyValidateOptions{/// <summary>/// Validates a specific named options instance (or all when <paramref name="name"/> is <see langword="null" />)./// </summary>/// <param name="name">The name of the options instance being validated.</param>/// <param name="options">The options instance.</param>/// <returns>Validation result.</returns>[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration","10.0.12.23009")]
#if !NET10_0_OR_GREATER[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming","IL2026:RequiresUnreferencedCode",Justification="The created ValidationContext object is used in a way that never call reflection")]
#endif
publicglobal::Microsoft.Extensions.Options.ValidateOptionsResultValidate(string?name,global::Microsoft.Diagnostics.Tools.Monitor.MyOptionsoptions){global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder?builder=null;
#if NET10_0_OR_GREATERstringdisplayName=string.IsNullOrEmpty(name)?"MyOptions.Validate":$"{name}.Validate";varcontext=newglobal::System.ComponentModel.DataAnnotations.ValidationContext(options,displayName,null,null);
#else
varcontext=newglobal::System.ComponentModel.DataAnnotations.ValidationContext(options);
#endif
context.MemberName="Validate";context.DisplayName=string.IsNullOrEmpty(name)?"MyOptions.Validate":$"{name}.Validate";(builder??=new()).AddResults(((global::System.ComponentModel.DataAnnotations.IValidatableObject)options).Validate(context));returnbuilderisnull?global::Microsoft.Extensions.Options.ValidateOptionsResult.Success:builder.Build();}}
Note that the construction of the ValidationContext passes null for the IServiceProvider parameter.
This prevents IValidatableObject implementations from using the ValidationContext.GetService method because it will always return null. Here are a few examples where .NET Monitor uses this and would prevent it from adopting options validation source generation:
Not to necessarily prescribe the solution, but it would be nice if the source generator would detect an IServiceProvider parameter from the primary constructor or possibly a field from the IValidateOptions<T> implementation and pass that instance when constructing the ValidationContext.
The text was updated successfully, but these errors were encountered:
Using the following example source:
would generate an options validation implementation that looks like:
Note that the construction of the
ValidationContext
passes null for theIServiceProvider
parameter.It appears that the generator does not consider if an
IServiceProvider
is available: https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs#L697This prevents
IValidatableObject
implementations from using theValidationContext.GetService
method because it will always return null. Here are a few examples where .NET Monitor uses this and would prevent it from adopting options validation source generation:Not to necessarily prescribe the solution, but it would be nice if the source generator would detect an
IServiceProvider
parameter from the primary constructor or possibly a field from theIValidateOptions<T>
implementation and pass that instance when constructing theValidationContext
.The text was updated successfully, but these errors were encountered: