RSCG – Microsoft.Extensions.Options.Generators.OptionsValidatorGenerator
RSCG – Microsoft.Extensions.Options.Generators.OptionsValidatorGenerator
name | Microsoft.Extensions.Options.Generators.OptionsValidatorGenerator |
nuget | https://www.nuget.org/packages/Microsoft.Extensions.Options |
link | https://learn.microsoft.com/en-us/dotnet/core/extensions/options-validation-generator |
author | Microsoft |
Generating the validation for data annotations on options classes.
This is how you can use Microsoft.Extensions.Options.Generators.OptionsValidatorGenerator .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" /> </ItemGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> </Project>
The code that you will use is
namespace DemoValidatorObj; [OptionsValidator] public partial class ValidatorForMyApp : IValidateOptions<MyAppOptions> { } //public class SecondModelNoNamespace //{ // [Required] // [MinLength(5)] // public string P4 { get; set; } = string.Empty; //} //[OptionsValidator] //public partial class SecondValidatorNoNamespace // : IValidateOptions<SecondModelNoNamespace> //{ //}
namespace DemoValidatorObj; [DebuggerDisplay("{AppDisplayName}")] public class MyAppOptions { public const string ConfigName = "MyAppOptionsInConfig"; [Required] [MinLength(3)] public string AppDisplayName { get; set; } = string.Empty; //[ValidateObjectMembers( // typeof(SecondValidatorNoNamespace))] //public SecondModelNoNamespace? P2 { get; set; } } //[OptionsValidator] //public partial class SecondValidatorNoNamespace // : IValidateOptions<SecondModelNoNamespace> //{ //}
The code that is generated is
// <auto-generated/> #nullable enable #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103 namespace DemoValidatorObj { partial class ValidatorForMyApp { /// <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", "8.0.9.3103")] [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode", Justification = "The created ValidationContext object is used in a way that never call reflection")] public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::DemoValidatorObj.MyAppOptions options) { global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder? builder = null; var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options); var validationResults = new global::System.Collections.Generic.List<global::System.ComponentModel.DataAnnotations.ValidationResult>(); var validationAttributes = new global::System.Collections.Generic.List<global::System.ComponentModel.DataAnnotations.ValidationAttribute>(2); context.MemberName = "AppDisplayName"; context.DisplayName = string.IsNullOrEmpty(name) ? "MyAppOptions.AppDisplayName" : $"{name}.AppDisplayName"; validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1); validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2); if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.AppDisplayName, context, validationResults, validationAttributes)) { (builder ??= new()).AddResults(validationResults); } return builder is null ? global::Microsoft.Extensions.Options.ValidateOptionsResult.Success : builder.Build(); } } } namespace __OptionValidationStaticInstances { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "8.0.9.3103")] file static class __Attributes { internal static readonly global::System.ComponentModel.DataAnnotations.RequiredAttribute A1 = new global::System.ComponentModel.DataAnnotations.RequiredAttribute(); internal static readonly __OptionValidationGeneratedAttributes.__SourceGen__MinLengthAttribute A2 = new __OptionValidationGeneratedAttributes.__SourceGen__MinLengthAttribute( (int)3); } } namespace __OptionValidationStaticInstances { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "8.0.9.3103")] file static class __Validators { } } namespace __OptionValidationGeneratedAttributes { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "8.0.9.3103")] [global::System.AttributeUsage(global::System.AttributeTargets.Property | global::System.AttributeTargets.Field | global::System.AttributeTargets.Parameter, AllowMultiple = false)] file class __SourceGen__MinLengthAttribute : global::System.ComponentModel.DataAnnotations.ValidationAttribute { private static string DefaultErrorMessageString => "The field {0} must be a string or array type with a minimum length of '{1}'."; public __SourceGen__MinLengthAttribute(int length) : base(() => DefaultErrorMessageString) { Length = length; } public int Length { get; } public override bool IsValid(object? value) { if (Length < -1) { throw new global::System.InvalidOperationException("MinLengthAttribute must have a Length value that is zero or greater."); } if (value == null) { return true; } int length; if (value is string stringValue) { length = stringValue.Length; } else if (value is System.Collections.ICollection collectionValue) { length = collectionValue.Count; } else { throw new global::System.InvalidCastException($"The field of type {value.GetType()} must be a string, array, or ICollection type."); } return length >= Length; } public override string FormatErrorMessage(string name) => string.Format(global::System.Globalization.CultureInfo.CurrentCulture, ErrorMessageString, name, Length); } }
Code and pdf at https://ignatandrei.github.io/RSCG_Examples/v2/docs/Microsoft.Extensions.Options.Generators.OptionsValidatorGenerator
Leave a Reply