| __`SYSLIB1116`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1117`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1118`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
-
+| __`SYSLIB1201`__ | Options validation generator: Can't use 'ValidateObjectMembersAttribute' or `ValidateEnumeratedItemsAttribute` on fields or properties with open generic types. |
+| __`SYSLIB1202`__ | Options validation generator: A member type has no fields or properties to validate. |
+| __`SYSLIB1203`__ | Options validation generator: A type has no fields or properties to validate. |
+| __`SYSLIB1204`__ | Options validation generator: A type annotated with `OptionsValidatorAttribute` doesn't implement the necessary interface. |
+| __`SYSLIB1205`__ | Options validation generator: A type already includes an implementation of the 'Validate' method. |
+| __`SYSLIB1206`__ | Options validation generator: Can't validate private fields or properties. |
+| __`SYSLIB1207`__ | Options validation generator: Member type is not enumerable. |
+| __`SYSLIB1208`__ | Options validation generator: Validators used for transitive or enumerable validation must have a constructor with no parameters. |
+| __`SYSLIB1209`__ | Options validation generator: `OptionsValidatorAttribute` can't be applied to a static class. |
+| __`SYSLIB1210`__ | Options validation generator: Null validator type specified for the `ValidateObjectMembersAttribute` or 'ValidateEnumeratedItemsAttribute' attributes. |
+| __`SYSLIB1211`__ | Options validation generator: Unsupported circular references in model types. |
+| __`SYSLIB1212`__ | Options validation generator: Member potentially missing transitive validation. |
+| __`SYSLIB1213`__ | Options validation generator: Member potentially missing enumerable validation. |
+| __`SYSLIB1214`__ | *_`SYSLIB1214`-`SYSLIB1218` reserved for Microsoft.Extensions.Options.SourceGeneration.* |
+| __`SYSLIB1215`__ | *_`SYSLIB1214`-`SYSLIB1218` reserved for Microsoft.Extensions.Options.SourceGeneration.* |
+| __`SYSLIB1216`__ | *_`SYSLIB1214`-`SYSLIB1218` reserved for Microsoft.Extensions.Options.SourceGeneration.* |
+| __`SYSLIB1217`__ | *_`SYSLIB1214`-`SYSLIB1218` reserved for Microsoft.Extensions.Options.SourceGeneration.* |
+| __`SYSLIB1218`__ | *_`SYSLIB1214`-`SYSLIB1218` reserved for Microsoft.Extensions.Options.SourceGeneration.* |
### Diagnostic Suppressions (`SYSLIBSUPPRESS****`)
[DoesNotReturn]
#endif
private static void Throw(string? paramName) => throw new ArgumentNullException(paramName);
+
+ /// <summary>
+ /// Throws either an <see cref="System.ArgumentNullException"/> or an <see cref="System.ArgumentException"/>
+ /// if the specified string is <see langword="null"/> or whitespace respectively.
+ /// </summary>
+ /// <param name="argument">String to be checked for <see langword="null"/> or whitespace.</param>
+ /// <param name="paramName">The name of the parameter being checked.</param>
+ /// <returns>The original value of <paramref name="argument"/>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#if NETCOREAPP3_0_OR_GREATER
+ [return: NotNull]
+#endif
+ public static string IfNullOrWhitespace(
+#if NETCOREAPP3_0_OR_GREATER
+ [NotNull]
+#endif
+ string? argument,
+ [CallerArgumentExpression(nameof(argument))] string paramName = "")
+ {
+#if !NETCOREAPP3_1_OR_GREATER
+ if (argument == null)
+ {
+ throw new ArgumentNullException(paramName);
+ }
+#endif
+
+ if (string.IsNullOrWhiteSpace(argument))
+ {
+ if (argument == null)
+ {
+ throw new ArgumentNullException(paramName);
+ }
+ else
+ {
+ throw new ArgumentException(paramName, "Argument is whitespace");
+ }
+ }
+
+ return argument;
+ }
}
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.CodeAnalysis;
+using System;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ internal sealed class DiagDescriptors : DiagDescriptorsBase
+ {
+ private const string Category = "Microsoft.Extensions.Options.SourceGeneration";
+
+ public static DiagnosticDescriptor CantUseWithGenericTypes { get; } = Make(
+ id: "SYSLIB1201",
+ title: SR.CantUseWithGenericTypesTitle,
+ messageFormat: SR.CantUseWithGenericTypesMessage,
+ category: Category);
+
+ public static DiagnosticDescriptor NoEligibleMember { get; } = Make(
+ id: "SYSLIB1202",
+ title: SR.NoEligibleMemberTitle,
+ messageFormat: SR.NoEligibleMemberMessage,
+ category: Category,
+ defaultSeverity: DiagnosticSeverity.Warning);
+
+ public static DiagnosticDescriptor NoEligibleMembersFromValidator { get; } = Make(
+ id: "SYSLIB1203",
+ title: SR.NoEligibleMembersFromValidatorTitle,
+ messageFormat: SR.NoEligibleMembersFromValidatorMessage,
+ category: Category,
+ defaultSeverity: DiagnosticSeverity.Warning);
+
+ public static DiagnosticDescriptor DoesntImplementIValidateOptions { get; } = Make(
+ id: "SYSLIB1204",
+ title: SR.DoesntImplementIValidateOptionsTitle,
+ messageFormat: SR.DoesntImplementIValidateOptionsMessage,
+ category: Category);
+
+ public static DiagnosticDescriptor AlreadyImplementsValidateMethod { get; } = Make(
+ id: "SYSLIB1205",
+ title: SR.AlreadyImplementsValidateMethodTitle,
+ messageFormat: SR.AlreadyImplementsValidateMethodMessage,
+ category: Category);
+
+ public static DiagnosticDescriptor MemberIsInaccessible { get; } = Make(
+ id: "SYSLIB1206",
+ title: SR.MemberIsInaccessibleTitle,
+ messageFormat: SR.MemberIsInaccessibleMessage,
+ category: Category);
+
+ public static DiagnosticDescriptor NotEnumerableType { get; } = Make(
+ id: "SYSLIB1207",
+ title: SR.NotEnumerableTypeTitle,
+ messageFormat: SR.NotEnumerableTypeMessage,
+ category: Category);
+
+ public static DiagnosticDescriptor ValidatorsNeedSimpleConstructor { get; } = Make(
+ id: "SYSLIB1208",
+ title: SR.ValidatorsNeedSimpleConstructorTitle,
+ messageFormat: SR.ValidatorsNeedSimpleConstructorMessage,
+ category: Category);
+
+ public static DiagnosticDescriptor CantBeStaticClass { get; } = Make(
+ id: "SYSLIB1209",
+ title: SR.CantBeStaticClassTitle,
+ messageFormat: SR.CantBeStaticClassMessage,
+ category: Category);
+
+ public static DiagnosticDescriptor NullValidatorType { get; } = Make(
+ id: "SYSLIB1210",
+ title: SR.NullValidatorTypeTitle,
+ messageFormat: SR.NullValidatorTypeMessage,
+ category: Category);
+
+ public static DiagnosticDescriptor CircularTypeReferences { get; } = Make(
+ id: "SYSLIB1211",
+ title: SR.CircularTypeReferencesTitle,
+ messageFormat: SR.CircularTypeReferencesMessage,
+ category: Category);
+
+ public static DiagnosticDescriptor PotentiallyMissingTransitiveValidation { get; } = Make(
+ id: "SYSLIB1212",
+ title: SR.PotentiallyMissingTransitiveValidationTitle,
+ messageFormat: SR.PotentiallyMissingTransitiveValidationMessage,
+ category: Category,
+ defaultSeverity: DiagnosticSeverity.Warning);
+
+ public static DiagnosticDescriptor PotentiallyMissingEnumerableValidation { get; } = Make(
+ id: "SYSLIB1213",
+ title: SR.PotentiallyMissingEnumerableValidationTitle,
+ messageFormat: SR.PotentiallyMissingEnumerableValidationMessage,
+ category: Category,
+ defaultSeverity: DiagnosticSeverity.Warning);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using Microsoft.CodeAnalysis;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ #pragma warning disable CA1052 // Static holder types should be Static or NotInheritable
+ internal class DiagDescriptorsBase
+ #pragma warning restore CA1052
+ {
+ protected static DiagnosticDescriptor Make(
+ string id,
+ string title,
+ string messageFormat,
+ string category,
+ DiagnosticSeverity defaultSeverity = DiagnosticSeverity.Error,
+ bool isEnabledByDefault = true)
+ {
+ return new(
+ id,
+ title,
+ messageFormat,
+ category,
+ defaultSeverity,
+ isEnabledByDefault);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ /// <summary>
+ /// Emits option validation.
+ /// </summary>
+ internal sealed class Emitter : EmitterBase
+ {
+ private const string StaticValidationAttributeHolderClassName = "__Attributes";
+ private const string StaticValidatorHolderClassName = "__Validators";
+ private const string StaticFieldHolderClassesNamespace = "__OptionValidationStaticInstances";
+ private const string StaticValidationAttributeHolderClassFQN = $"global::{StaticFieldHolderClassesNamespace}.{StaticValidationAttributeHolderClassName}";
+ private const string StaticValidatorHolderClassFQN = $"global::{StaticFieldHolderClassesNamespace}.{StaticValidatorHolderClassName}";
+ private const string StaticListType = "global::System.Collections.Generic.List";
+ private const string StaticValidationResultType = "global::System.ComponentModel.DataAnnotations.ValidationResult";
+ private const string StaticValidationAttributeType = "global::System.ComponentModel.DataAnnotations.ValidationAttribute";
+
+ private sealed record StaticFieldInfo(string FieldTypeFQN, int FieldOrder, string FieldName, IList<string> InstantiationLines);
+
+ public string Emit(
+ IEnumerable<ValidatorType> validatorTypes,
+ CancellationToken cancellationToken)
+ {
+ var staticValidationAttributesDict = new Dictionary<string, StaticFieldInfo>();
+ var staticValidatorsDict = new Dictionary<string, StaticFieldInfo>();
+
+ foreach (var vt in validatorTypes.OrderBy(static lt => lt.Namespace + "." + lt.Name))
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ GenValidatorType(vt, ref staticValidationAttributesDict, ref staticValidatorsDict);
+ }
+
+ GenStaticClassWithStaticReadonlyFields(staticValidationAttributesDict.Values, StaticFieldHolderClassesNamespace, StaticValidationAttributeHolderClassName);
+ GenStaticClassWithStaticReadonlyFields(staticValidatorsDict.Values, StaticFieldHolderClassesNamespace, StaticValidatorHolderClassName);
+
+ return Capture();
+ }
+
+ private void GenValidatorType(ValidatorType vt, ref Dictionary<string, StaticFieldInfo> staticValidationAttributesDict, ref Dictionary<string, StaticFieldInfo> staticValidatorsDict)
+ {
+ if (vt.Namespace.Length > 0)
+ {
+ OutLn($"namespace {vt.Namespace}");
+ OutOpenBrace();
+ }
+
+ foreach (var p in vt.ParentTypes)
+ {
+ OutLn(p);
+ OutOpenBrace();
+ }
+
+ if (vt.IsSynthetic)
+ {
+ OutGeneratedCodeAttribute();
+ OutLn($"internal sealed partial {vt.DeclarationKeyword} {vt.Name}");
+ }
+ else
+ {
+ OutLn($"partial {vt.DeclarationKeyword} {vt.Name}");
+ }
+
+ OutOpenBrace();
+
+ for (var i = 0; i < vt.ModelsToValidate.Count; i++)
+ {
+ var modelToValidate = vt.ModelsToValidate[i];
+
+ GenModelValidationMethod(modelToValidate, vt.IsSynthetic, ref staticValidationAttributesDict, ref staticValidatorsDict);
+ }
+
+ OutCloseBrace();
+
+ foreach (var _ in vt.ParentTypes)
+ {
+ OutCloseBrace();
+ }
+
+ if (vt.Namespace.Length > 0)
+ {
+ OutCloseBrace();
+ }
+ }
+
+ private void GenStaticClassWithStaticReadonlyFields(IEnumerable<StaticFieldInfo> staticFields, string classNamespace, string className)
+ {
+ OutLn($"namespace {classNamespace}");
+ OutOpenBrace();
+
+ OutGeneratedCodeAttribute();
+ OutLn($"internal static class {className}");
+ OutOpenBrace();
+
+ var staticValidationAttributes = staticFields
+ .OrderBy(x => x.FieldOrder)
+ .ToArray();
+
+ for (var i = 0; i < staticValidationAttributes.Length; i++)
+ {
+ var attributeInstance = staticValidationAttributes[i];
+ OutIndent();
+ Out($"internal static readonly {attributeInstance.FieldTypeFQN} {attributeInstance.FieldName} = ");
+ for (var j = 0; j < attributeInstance.InstantiationLines.Count; j++)
+ {
+ var line = attributeInstance.InstantiationLines[j];
+ Out(line);
+ if (j != attributeInstance.InstantiationLines.Count - 1)
+ {
+ OutLn();
+ OutIndent();
+ }
+ else
+ {
+ Out(';');
+ }
+ }
+
+ OutLn();
+
+ if (i != staticValidationAttributes.Length - 1)
+ {
+ OutLn();
+ }
+ }
+
+ OutCloseBrace();
+
+ OutCloseBrace();
+ }
+
+ private void GenModelSelfValidationIfNecessary(ValidatedModel modelToValidate)
+ {
+ if (modelToValidate.SelfValidates)
+ {
+ OutLn($"builder.AddResults(((global::System.ComponentModel.DataAnnotations.IValidatableObject)options).Validate(context));");
+ OutLn();
+ }
+ }
+
+ private void GenModelValidationMethod(
+ ValidatedModel modelToValidate,
+ bool makeStatic,
+ ref Dictionary<string, StaticFieldInfo> staticValidationAttributesDict,
+ ref Dictionary<string, StaticFieldInfo> staticValidatorsDict)
+ {
+ OutLn($"/// <summary>");
+ OutLn($"/// Validates a specific named options instance (or all when <paramref name=\"name\"/> is <see langword=\"null\" />).");
+ OutLn($"/// </summary>");
+ OutLn($"/// <param name=\"name\">The name of the options instance being validated.</param>");
+ OutLn($"/// <param name=\"options\">The options instance.</param>");
+ OutLn($"/// <returns>Validation result.</returns>");
+ OutGeneratedCodeAttribute();
+
+ OutLn($"public {(makeStatic ? "static " : string.Empty)}global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, {modelToValidate.Name} options)");
+ OutOpenBrace();
+ OutLn($"var baseName = (string.IsNullOrEmpty(name) ? \"{modelToValidate.SimpleName}\" : name) + \".\";");
+ OutLn($"var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();");
+ OutLn($"var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options);");
+
+ int capacity = modelToValidate.MembersToValidate.Max(static vm => vm.ValidationAttributes.Count);
+ if (capacity > 0)
+ {
+ OutLn($"var validationResults = new {StaticListType}<{StaticValidationResultType}>();");
+ OutLn($"var validationAttributes = new {StaticListType}<{StaticValidationAttributeType}>({capacity});");
+ }
+ OutLn();
+
+ bool cleanListsBeforeUse = false;
+ foreach (var vm in modelToValidate.MembersToValidate)
+ {
+ if (vm.ValidationAttributes.Count > 0)
+ {
+ GenMemberValidation(vm, ref staticValidationAttributesDict, cleanListsBeforeUse);
+ cleanListsBeforeUse = true;
+ OutLn();
+ }
+
+ if (vm.TransValidatorType is not null)
+ {
+ GenTransitiveValidation(vm, ref staticValidatorsDict);
+ OutLn();
+ }
+
+ if (vm.EnumerationValidatorType is not null)
+ {
+ GenEnumerationValidation(vm, ref staticValidatorsDict);
+ OutLn();
+ }
+ }
+
+ GenModelSelfValidationIfNecessary(modelToValidate);
+ OutLn($"return builder.Build();");
+ OutCloseBrace();
+ }
+
+ private void GenMemberValidation(ValidatedMember vm, ref Dictionary<string, StaticFieldInfo> staticValidationAttributesDict, bool cleanListsBeforeUse)
+ {
+ OutLn($"context.MemberName = \"{vm.Name}\";");
+ OutLn($"context.DisplayName = baseName + \"{vm.Name}\";");
+
+ if (cleanListsBeforeUse)
+ {
+ OutLn($"validationResults.Clear();");
+ OutLn($"validationAttributes.Clear();");
+ }
+
+ foreach (var attr in vm.ValidationAttributes)
+ {
+ var staticValidationAttributeInstance = GetOrAddStaticValidationAttribute(ref staticValidationAttributesDict, attr);
+ OutLn($"validationAttributes.Add({StaticValidationAttributeHolderClassFQN}.{staticValidationAttributeInstance.FieldName});");
+ }
+
+ OutLn($"if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.{vm.Name}!, context, validationResults, validationAttributes))");
+ OutOpenBrace();
+ OutLn($"builder.AddResults(validationResults);");
+ OutCloseBrace();
+ }
+
+ private StaticFieldInfo GetOrAddStaticValidationAttribute(ref Dictionary<string, StaticFieldInfo> staticValidationAttributesDict, ValidationAttributeInfo attr)
+ {
+ var attrInstantiationStatementLines = new List<string>();
+
+ if (attr.ConstructorArguments.Count > 0)
+ {
+ attrInstantiationStatementLines.Add($"new {attr.AttributeName}(");
+
+ for (var i = 0; i < attr.ConstructorArguments.Count; i++)
+ {
+ if (i != attr.ConstructorArguments.Count - 1)
+ {
+ attrInstantiationStatementLines.Add($"{GetPaddingString(1)}{attr.ConstructorArguments[i]},");
+ }
+ else
+ {
+ attrInstantiationStatementLines.Add($"{GetPaddingString(1)}{attr.ConstructorArguments[i]})");
+ }
+ }
+ }
+ else
+ {
+ attrInstantiationStatementLines.Add($"new {attr.AttributeName}()");
+ }
+
+ if (attr.Properties.Count > 0)
+ {
+ attrInstantiationStatementLines.Add("{");
+
+ var propertiesOrderedByKey = attr.Properties
+ .OrderBy(p => p.Key)
+ .ToArray();
+
+ for (var i = 0; i < propertiesOrderedByKey.Length; i++)
+ {
+ var prop = propertiesOrderedByKey[i];
+ var notLast = i != propertiesOrderedByKey.Length - 1;
+ attrInstantiationStatementLines.Add($"{GetPaddingString(1)}{prop.Key} = {prop.Value}{(notLast ? "," : string.Empty)}");
+ }
+
+ attrInstantiationStatementLines.Add("}");
+ }
+
+ var instantiationStatement = string.Join(Environment.NewLine, attrInstantiationStatementLines);
+
+ if (!staticValidationAttributesDict.TryGetValue(instantiationStatement, out var staticValidationAttributeInstance))
+ {
+ var fieldNumber = staticValidationAttributesDict.Count + 1;
+ staticValidationAttributeInstance = new StaticFieldInfo(
+ FieldTypeFQN: attr.AttributeName,
+ FieldOrder: fieldNumber,
+ FieldName: $"A{fieldNumber}",
+ InstantiationLines: attrInstantiationStatementLines);
+
+ staticValidationAttributesDict.Add(instantiationStatement, staticValidationAttributeInstance);
+ }
+
+ return staticValidationAttributeInstance;
+ }
+
+ private void GenTransitiveValidation(ValidatedMember vm, ref Dictionary<string, StaticFieldInfo> staticValidatorsDict)
+ {
+ string callSequence;
+ if (vm.TransValidateTypeIsSynthetic)
+ {
+ callSequence = vm.TransValidatorType!;
+ }
+ else
+ {
+ var staticValidatorInstance = GetOrAddStaticValidator(ref staticValidatorsDict, vm.TransValidatorType!);
+
+ callSequence = $"{StaticValidatorHolderClassFQN}.{staticValidatorInstance.FieldName}";
+ }
+
+ var valueAccess = (vm.IsNullable && vm.IsValueType) ? ".Value" : string.Empty;
+
+ if (vm.IsNullable)
+ {
+ OutLn($"if (options.{vm.Name} is not null)");
+ OutOpenBrace();
+ OutLn($"builder.AddResult({callSequence}.Validate(baseName + \"{vm.Name}\", options.{vm.Name}{valueAccess}));");
+ OutCloseBrace();
+ }
+ else
+ {
+ OutLn($"builder.AddResult({callSequence}.Validate(baseName + \"{vm.Name}\", options.{vm.Name}{valueAccess}));");
+ }
+ }
+
+ private void GenEnumerationValidation(ValidatedMember vm, ref Dictionary<string, StaticFieldInfo> staticValidatorsDict)
+ {
+ var valueAccess = (vm.IsValueType && vm.IsNullable) ? ".Value" : string.Empty;
+ var enumeratedValueAccess = (vm.EnumeratedIsNullable && vm.EnumeratedIsValueType) ? ".Value" : string.Empty;
+ string callSequence;
+ if (vm.EnumerationValidatorTypeIsSynthetic)
+ {
+ callSequence = vm.EnumerationValidatorType!;
+ }
+ else
+ {
+ var staticValidatorInstance = GetOrAddStaticValidator(ref staticValidatorsDict, vm.EnumerationValidatorType!);
+
+ callSequence = $"{StaticValidatorHolderClassFQN}.{staticValidatorInstance.FieldName}";
+ }
+
+ if (vm.IsNullable)
+ {
+ OutLn($"if (options.{vm.Name} is not null)");
+ }
+
+ OutOpenBrace();
+
+ OutLn($"var count = 0;");
+ OutLn($"foreach (var o in options.{vm.Name}{valueAccess})");
+ OutOpenBrace();
+
+ if (vm.EnumeratedIsNullable)
+ {
+ OutLn($"if (o is not null)");
+ OutOpenBrace();
+ OutLn($"builder.AddResult({callSequence}.Validate(baseName + $\"{vm.Name}[{{count}}]\", o{enumeratedValueAccess}));");
+ OutCloseBrace();
+
+ if (!vm.EnumeratedMayBeNull)
+ {
+ OutLn($"else");
+ OutOpenBrace();
+ OutLn($"builder.AddError(baseName + $\"{vm.Name}[{{count}}] is null\");");
+ OutCloseBrace();
+ }
+
+ OutLn($"count++;");
+ }
+ else
+ {
+ OutLn($"builder.AddResult({callSequence}.Validate(baseName + $\"{vm.Name}[{{count++}}]\", o{enumeratedValueAccess}));");
+ }
+
+ OutCloseBrace();
+ OutCloseBrace();
+ }
+
+ #pragma warning disable CA1822 // Mark members as static: static should come before non-static, but we want the method to be here
+ private StaticFieldInfo GetOrAddStaticValidator(ref Dictionary<string, StaticFieldInfo> staticValidatorsDict, string validatorTypeFQN)
+ #pragma warning restore CA1822
+ {
+ if (!staticValidatorsDict.TryGetValue(validatorTypeFQN, out var staticValidatorInstance))
+ {
+ var fieldNumber = staticValidatorsDict.Count + 1;
+ staticValidatorInstance = new StaticFieldInfo(
+ FieldTypeFQN: validatorTypeFQN,
+ FieldOrder: fieldNumber,
+ FieldName: $"V{fieldNumber}",
+ InstantiationLines: new[] { $"new {validatorTypeFQN}()" });
+
+ staticValidatorsDict.Add(validatorTypeFQN, staticValidatorInstance);
+ }
+
+ return staticValidatorInstance;
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+using System.Text;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ internal class EmitterBase
+ {
+ public static string GeneratedCodeAttribute { get; } = $"global::System.CodeDom.Compiler.GeneratedCodeAttribute(" +
+ $"\"{typeof(EmitterBase).Assembly.GetName().Name}\", " +
+ $"\"{typeof(EmitterBase).Assembly.GetName().Version}\")";
+
+ public static string FilePreamble { get; } = @$"
+ // <auto-generated/>
+ #nullable enable
+ #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103
+ ";
+
+ private const int DefaultStringBuilderCapacity = 1024;
+ private const int IndentChars = 4;
+
+ private readonly StringBuilder _sb = new(DefaultStringBuilderCapacity);
+ private readonly string[] _padding = new string[16];
+ private int _indent;
+
+ public EmitterBase(bool emitPreamble = true)
+ {
+ var padding = _padding;
+ for (int i = 0; i < padding.Length; i++)
+ {
+ padding[i] = new string(' ', i * IndentChars);
+ }
+
+ if (emitPreamble)
+ {
+ Out(FilePreamble);
+ }
+ }
+
+ protected void OutOpenBrace()
+ {
+ OutLn("{");
+ Indent();
+ }
+
+ protected void OutCloseBrace()
+ {
+ Unindent();
+ OutLn("}");
+ }
+
+ protected void OutCloseBraceWithExtra(string extra)
+ {
+ Unindent();
+ OutIndent();
+ Out("}");
+ Out(extra);
+ OutLn();
+ }
+
+ protected void OutIndent()
+ {
+ _ = _sb.Append(_padding[_indent]);
+ }
+
+ protected string GetPaddingString(byte indent)
+ {
+ return _padding[indent];
+ }
+
+ protected void OutLn()
+ {
+ _ = _sb.AppendLine();
+ }
+
+ protected void OutLn(string line)
+ {
+ OutIndent();
+ _ = _sb.AppendLine(line);
+ }
+
+ protected void OutPP(string line)
+ {
+ _ = _sb.AppendLine(line);
+ }
+
+ protected void OutEnumeration(IEnumerable<string> e)
+ {
+ bool first = true;
+ foreach (var item in e)
+ {
+ if (!first)
+ {
+ Out(", ");
+ }
+
+ Out(item);
+ first = false;
+ }
+ }
+
+ protected void Out(string text) => _ = _sb.Append(text);
+ protected void Out(char ch) => _ = _sb.Append(ch);
+ protected void Indent() => _indent++;
+ protected void Unindent() => _indent--;
+ protected void OutGeneratedCodeAttribute() => OutLn($"[{GeneratedCodeAttribute}]");
+ protected string Capture() => _sb.ToString();
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Text;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ [Generator]
+ public class Generator : IIncrementalGenerator
+ {
+ public void Initialize(IncrementalGeneratorInitializationContext context)
+ {
+ IncrementalValuesProvider<(TypeDeclarationSyntax TypeSyntax, SemanticModel SemanticModel)> typeDeclarations = context.SyntaxProvider
+ .ForAttributeWithMetadataName(
+ SymbolLoader.OptionsValidatorAttribute,
+ (node, _) => node is TypeDeclarationSyntax,
+ (context, _) => (TypeSyntax:context.TargetNode as TypeDeclarationSyntax, SemanticModel: context.SemanticModel))
+ .Where(static m => m.TypeSyntax is not null);
+
+ IncrementalValueProvider<(Compilation, ImmutableArray<(TypeDeclarationSyntax TypeSyntax, SemanticModel SemanticModel)>)> compilationAndTypes =
+ context.CompilationProvider.Combine(typeDeclarations.Collect());
+
+ context.RegisterSourceOutput(compilationAndTypes, static (spc, source) => HandleAnnotatedTypes(source.Item1, source.Item2, spc));
+ }
+
+ private static void HandleAnnotatedTypes(Compilation compilation, ImmutableArray<(TypeDeclarationSyntax TypeSyntax, SemanticModel SemanticModel)> types, SourceProductionContext context)
+ {
+ if (!SymbolLoader.TryLoad(compilation, out var symbolHolder))
+ {
+ // Not eligible compilation
+ return;
+ }
+
+ var parser = new Parser(compilation, context.ReportDiagnostic, symbolHolder!, context.CancellationToken);
+
+ var validatorTypes = parser.GetValidatorTypes(types);
+ if (validatorTypes.Count > 0)
+ {
+ var emitter = new Emitter();
+ var result = emitter.Emit(validatorTypes, context.CancellationToken);
+
+ context.AddSource("Validators.g.cs", SourceText.From(result, Encoding.UTF8));
+ }
+ }
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFramework>netstandard2.0</TargetFramework>
+ <CLSCompliant>false</CLSCompliant>
+ <EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
+ <UsingToolXliff>true</UsingToolXliff>
+ <AnalyzerLanguage>cs</AnalyzerLanguage>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <AnalyzerRoslynVersion>4.4</AnalyzerRoslynVersion>
+ <RoslynApiVersion>$(MicrosoftCodeAnalysisVersion_4_4)</RoslynApiVersion>
+ <DefineConstants Condition="'$(LaunchDebugger)' == 'true'">$(DefineConstants);ROSLYN4_4_OR_GREATER</DefineConstants>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(MicrosoftCodeAnalysisVersion_4_4)" PrivateAssets="all" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="$(CoreLibSharedDir)System\Runtime\CompilerServices\IsExternalInit.cs" Link="Common\System\Runtime\CompilerServices\IsExternalInit.cs" />
+ <Compile Include="DiagDescriptors.cs" />
+ <Compile Include="DiagDescriptorsBase.cs" />
+ <Compile Include="Emitter.cs" />
+ <Compile Include="EmitterBase.cs" />
+ <Compile Include="Generator.cs" />
+ <Compile Include="Model\ValidatedMember.cs" />
+ <Compile Include="Model\ValidatedModel.cs" />
+ <Compile Include="Model\ValidationAttributeInfo.cs" />
+ <Compile Include="Model\ValidatorType.cs" />
+ <Compile Include="Parser.cs" />
+ <Compile Include="ParserUtilities.cs" />
+ <Compile Include="SymbolHolder.cs" />
+ <Compile Include="SymbolLoader.cs" />
+ <Compile Include="TypeDeclarationSyntaxReceiver.cs" />
+ </ItemGroup>
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ internal sealed record class ValidatedMember(
+ string Name,
+ List<ValidationAttributeInfo> ValidationAttributes,
+ string? TransValidatorType,
+ bool TransValidateTypeIsSynthetic,
+ string? EnumerationValidatorType,
+ bool EnumerationValidatorTypeIsSynthetic,
+ bool IsNullable,
+ bool IsValueType,
+ bool EnumeratedIsNullable,
+ bool EnumeratedIsValueType,
+ bool EnumeratedMayBeNull);
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ internal sealed record class ValidatedModel(
+ string Name,
+ string SimpleName,
+ bool SelfValidates,
+ List<ValidatedMember> MembersToValidate);
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ internal sealed record class ValidationAttributeInfo(string AttributeName)
+ {
+ public List<string> ConstructorArguments { get; } = new();
+ public Dictionary<string, string> Properties { get; } = new();
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ internal sealed record class ValidatorType(
+ string Namespace,
+ string Name,
+ string NameWithoutGenerics,
+ string DeclarationKeyword,
+ List<string> ParentTypes,
+ bool IsSynthetic,
+ IList<ValidatedModel> ModelsToValidate);
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ /// <summary>
+ /// Holds an internal parser class that extracts necessary information for generating IValidateOptions.
+ /// </summary>
+ internal sealed class Parser
+ {
+ private const int NumValidationMethodArgs = 2;
+
+ private readonly CancellationToken _cancellationToken;
+ private readonly Compilation _compilation;
+ private readonly Action<Diagnostic> _reportDiagnostic;
+ private readonly SymbolHolder _symbolHolder;
+ private readonly Dictionary<ITypeSymbol, ValidatorType> _synthesizedValidators = new(SymbolEqualityComparer.Default);
+ private readonly HashSet<ITypeSymbol> _visitedModelTypes = new(SymbolEqualityComparer.Default);
+
+ public Parser(
+ Compilation compilation,
+ Action<Diagnostic> reportDiagnostic,
+ SymbolHolder symbolHolder,
+ CancellationToken cancellationToken)
+ {
+ _compilation = compilation;
+ _cancellationToken = cancellationToken;
+ _reportDiagnostic = reportDiagnostic;
+ _symbolHolder = symbolHolder;
+ }
+
+ public IReadOnlyList<ValidatorType> GetValidatorTypes(IEnumerable<(TypeDeclarationSyntax TypeSyntax, SemanticModel SemanticModel)> classes)
+ {
+ var results = new List<ValidatorType>();
+
+ foreach (var group in classes.GroupBy(x => x.TypeSyntax.SyntaxTree))
+ {
+ SemanticModel? sm = null;
+ foreach (var typeDec in group)
+ {
+ TypeDeclarationSyntax syntax = typeDec.TypeSyntax;
+ _cancellationToken.ThrowIfCancellationRequested();
+ sm ??= typeDec.SemanticModel;
+
+ var validatorType = sm.GetDeclaredSymbol(syntax) as ITypeSymbol;
+ if (validatorType is not null)
+ {
+ if (validatorType.IsStatic)
+ {
+ Diag(DiagDescriptors.CantBeStaticClass, syntax.GetLocation());
+ continue;
+ }
+
+ _visitedModelTypes.Clear();
+
+ var modelTypes = GetModelTypes(validatorType);
+ if (modelTypes.Count == 0)
+ {
+ // validator doesn't implement IValidateOptions
+ Diag(DiagDescriptors.DoesntImplementIValidateOptions, syntax.GetLocation(), validatorType.Name);
+ continue;
+ }
+
+ var modelsValidatorTypeValidates = new List<ValidatedModel>(modelTypes.Count);
+
+ foreach (var modelType in modelTypes)
+ {
+ if (modelType.Kind == SymbolKind.ErrorType)
+ {
+ // the compiler will report this error for us
+ continue;
+ }
+ else
+ {
+ // keep track of the models we look at, to detect loops
+ _ = _visitedModelTypes.Add(modelType.WithNullableAnnotation(NullableAnnotation.None));
+ }
+
+ if (AlreadyImplementsValidateMethod(validatorType, modelType))
+ {
+ // this type already implements a validation function, we can't auto-generate a new one
+ Diag(DiagDescriptors.AlreadyImplementsValidateMethod, syntax.GetLocation(), validatorType.Name);
+ continue;
+ }
+
+ var membersToValidate = GetMembersToValidate(modelType, true);
+ if (membersToValidate.Count == 0)
+ {
+ // this type lacks any eligible members
+ Diag(DiagDescriptors.NoEligibleMembersFromValidator, syntax.GetLocation(), modelType.ToString(), validatorType.ToString());
+ continue;
+ }
+
+ modelsValidatorTypeValidates.Add(new ValidatedModel(
+ GetFQN(modelType),
+ modelType.Name,
+ ModelSelfValidates(modelType),
+ membersToValidate));
+ }
+
+ string keyword = GetTypeKeyword(validatorType);
+
+ // following code establishes the containment hierarchy for the generated type in terms of nested types
+
+ var parents = new List<string>();
+ var parent = syntax.Parent as TypeDeclarationSyntax;
+
+ while (parent is not null && IsAllowedKind(parent.Kind()))
+ {
+ parents.Add($"partial {GetTypeKeyword(parent)} {parent.Identifier}{parent.TypeParameterList} {parent.ConstraintClauses}");
+ parent = parent.Parent as TypeDeclarationSyntax;
+ }
+
+ parents.Reverse();
+
+ results.Add(new ValidatorType(
+ validatorType.ContainingNamespace.IsGlobalNamespace ? string.Empty : validatorType.ContainingNamespace.ToString(),
+ GetMinimalFQN(validatorType),
+ GetMinimalFQNWithoutGenerics(validatorType),
+ keyword,
+ parents,
+ false,
+ modelsValidatorTypeValidates));
+ }
+ }
+ }
+
+ results.AddRange(_synthesizedValidators.Values);
+ _synthesizedValidators.Clear();
+
+ return results;
+ }
+
+ private static bool IsAllowedKind(SyntaxKind kind) =>
+ kind == SyntaxKind.ClassDeclaration ||
+ kind == SyntaxKind.StructDeclaration ||
+ kind == SyntaxKind.RecordStructDeclaration ||
+ kind == SyntaxKind.RecordDeclaration;
+
+ private static string GetTypeKeyword(ITypeSymbol type)
+ {
+ if (type.IsReferenceType)
+ {
+ return type.IsRecord ? "record class" : "class";
+ }
+
+ return type.IsRecord ? "record struct" : "struct";
+ }
+
+ private static string GetTypeKeyword(TypeDeclarationSyntax type) =>
+ type.Kind() switch
+ {
+ SyntaxKind.ClassDeclaration => "class",
+ SyntaxKind.RecordDeclaration => "record class",
+ SyntaxKind.RecordStructDeclaration => "record struct",
+ _ => type.Keyword.ValueText,
+ };
+
+ private static string GetFQN(ISymbol type)
+ => type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat.WithMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier));
+
+ private static string GetMinimalFQN(ISymbol type)
+ => type.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat.AddGenericsOptions(SymbolDisplayGenericsOptions.IncludeTypeParameters));
+
+ private static string GetMinimalFQNWithoutGenerics(ISymbol type)
+ => type.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat.WithGenericsOptions(SymbolDisplayGenericsOptions.None));
+
+ /// <summary>
+ /// Checks whether the given validator already implement the IValidationOptions>T< interface.
+ /// </summary>
+ private static bool AlreadyImplementsValidateMethod(INamespaceOrTypeSymbol validatorType, ISymbol modelType)
+ => validatorType
+ .GetMembers("Validate")
+ .Where(m => m.Kind == SymbolKind.Method)
+ .Select(m => (IMethodSymbol)m)
+ .Any(m => m.Parameters.Length == NumValidationMethodArgs
+ && m.Parameters[0].Type.SpecialType == SpecialType.System_String
+ && SymbolEqualityComparer.Default.Equals(m.Parameters[1].Type, modelType));
+
+ /// <summary>
+ /// Checks whether the given type contain any unbound generic type arguments.
+ /// </summary>
+ private static bool HasOpenGenerics(ITypeSymbol type, out string genericType)
+ {
+ if (type is INamedTypeSymbol mt)
+ {
+ if (mt.IsGenericType)
+ {
+ foreach (var ta in mt.TypeArguments)
+ {
+ if (ta.TypeKind == TypeKind.TypeParameter)
+ {
+ genericType = ta.Name;
+ return true;
+ }
+ }
+ }
+ }
+ else if (type is ITypeParameterSymbol)
+ {
+ genericType = type.Name;
+ return true;
+ }
+ else if (type is IArrayTypeSymbol ats)
+ {
+ return HasOpenGenerics(ats.ElementType, out genericType);
+ }
+
+ genericType = string.Empty;
+ return false;
+ }
+
+ private ITypeSymbol? GetEnumeratedType(ITypeSymbol type)
+ {
+ if (type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T)
+ {
+ // extract the T from a Nullable<T>
+ type = ((INamedTypeSymbol)type).TypeArguments[0];
+ }
+
+ foreach (var implementingInterface in type.AllInterfaces)
+ {
+ if (SymbolEqualityComparer.Default.Equals(implementingInterface.OriginalDefinition, _compilation.GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T)))
+ {
+ return implementingInterface.TypeArguments.First();
+ }
+ }
+
+ return null;
+ }
+
+ private List<ValidatedMember> GetMembersToValidate(ITypeSymbol modelType, bool speculate)
+ {
+ // make a list of the most derived members in the model type
+
+ if (modelType.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T)
+ {
+ // extract the T from a Nullable<T>
+ modelType = ((INamedTypeSymbol)modelType).TypeArguments[0];
+ }
+
+ var members = modelType.GetMembers().ToList();
+ var addedMembers = new HashSet<string>(members.Select(m => m.Name));
+ var baseType = modelType.BaseType;
+ while (baseType is not null && baseType.SpecialType != SpecialType.System_Object)
+ {
+ var baseMembers = baseType.GetMembers().Where(m => !addedMembers.Contains(m.Name));
+ members.AddRange(baseMembers);
+ addedMembers.UnionWith(baseMembers.Select(m => m.Name));
+ baseType = baseType.BaseType;
+ }
+
+ var membersToValidate = new List<ValidatedMember>();
+ foreach (var member in members)
+ {
+ var memberInfo = GetMemberInfo(member, speculate);
+ if (memberInfo is not null)
+ {
+ if (member.DeclaredAccessibility != Accessibility.Public && member.DeclaredAccessibility != Accessibility.Internal)
+ {
+ Diag(DiagDescriptors.MemberIsInaccessible, member.Locations.First(), member.Name);
+ continue;
+ }
+
+ membersToValidate.Add(memberInfo);
+ }
+ }
+
+ return membersToValidate;
+ }
+
+ private ValidatedMember? GetMemberInfo(ISymbol member, bool speculate)
+ {
+ ITypeSymbol memberType;
+ switch (member)
+ {
+ case IPropertySymbol prop:
+ memberType = prop.Type;
+ break;
+ case IFieldSymbol field:
+ if (field.AssociatedSymbol is not null)
+ {
+ // a backing field for a property, don't need those
+ return null;
+ }
+
+ memberType = field.Type;
+ break;
+ default:
+ // we only care about properties and fields
+ return null;
+ }
+
+ var validationAttrs = new List<ValidationAttributeInfo>();
+ string? transValidatorTypeName = null;
+ string? enumerationValidatorTypeName = null;
+ var enumeratedIsNullable = false;
+ var enumeratedIsValueType = false;
+ var enumeratedMayBeNull = false;
+ var transValidatorIsSynthetic = false;
+ var enumerationValidatorIsSynthetic = false;
+
+ foreach (var attribute in member.GetAttributes().Where(a => a.AttributeClass is not null))
+ {
+ var attributeType = attribute.AttributeClass!;
+ var attrLoc = attribute.ApplicationSyntaxReference?.GetSyntax().GetLocation();
+
+ if (SymbolEqualityComparer.Default.Equals(attributeType, _symbolHolder.ValidateObjectMembersAttributeSymbol))
+ {
+ if (HasOpenGenerics(memberType, out var genericType))
+ {
+ Diag(DiagDescriptors.CantUseWithGenericTypes, attrLoc, genericType);
+ #pragma warning disable S1226 // Method parameters, caught exceptions and foreach variables' initial values should not be ignored
+ speculate = false;
+ #pragma warning restore S1226 // Method parameters, caught exceptions and foreach variables' initial values should not be ignored
+ continue;
+ }
+
+ if (attribute.ConstructorArguments.Length == 1)
+ {
+ var transValidatorType = attribute.ConstructorArguments[0].Value as INamedTypeSymbol;
+ if (transValidatorType is not null)
+ {
+ if (CanValidate(transValidatorType, memberType))
+ {
+ if (transValidatorType.Constructors.Where(c => !c.Parameters.Any()).Any())
+ {
+ transValidatorTypeName = transValidatorType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+ }
+ else
+ {
+ Diag(DiagDescriptors.ValidatorsNeedSimpleConstructor, attrLoc, transValidatorType.Name);
+ }
+ }
+ else
+ {
+ Diag(DiagDescriptors.DoesntImplementIValidateOptions, attrLoc, transValidatorType.Name, memberType.Name);
+ }
+ }
+ else
+ {
+ Diag(DiagDescriptors.NullValidatorType, attrLoc);
+ }
+ }
+ else if (!_visitedModelTypes.Add(memberType.WithNullableAnnotation(NullableAnnotation.None)))
+ {
+ Diag(DiagDescriptors.CircularTypeReferences, attrLoc, memberType.ToString());
+ speculate = false;
+ continue;
+ }
+
+ if (transValidatorTypeName == null)
+ {
+ transValidatorIsSynthetic = true;
+ transValidatorTypeName = AddSynthesizedValidator(memberType, member);
+ }
+
+ // pop the stack
+ _ = _visitedModelTypes.Remove(memberType.WithNullableAnnotation(NullableAnnotation.None));
+ }
+ else if (SymbolEqualityComparer.Default.Equals(attributeType, _symbolHolder.ValidateEnumeratedItemsAttributeSymbol))
+ {
+ var enumeratedType = GetEnumeratedType(memberType);
+ if (enumeratedType == null)
+ {
+ Diag(DiagDescriptors.NotEnumerableType, attrLoc, memberType);
+ speculate = false;
+ continue;
+ }
+
+ enumeratedIsNullable = enumeratedType.IsReferenceType || enumeratedType.NullableAnnotation == NullableAnnotation.Annotated;
+ enumeratedIsValueType = enumeratedType.IsValueType;
+ enumeratedMayBeNull = enumeratedType.NullableAnnotation == NullableAnnotation.Annotated;
+
+ if (HasOpenGenerics(enumeratedType, out var genericType))
+ {
+ Diag(DiagDescriptors.CantUseWithGenericTypes, attrLoc, genericType);
+ speculate = false;
+ continue;
+ }
+
+ if (attribute.ConstructorArguments.Length == 1)
+ {
+ var enumerationValidatorType = attribute.ConstructorArguments[0].Value as INamedTypeSymbol;
+ if (enumerationValidatorType is not null)
+ {
+ if (CanValidate(enumerationValidatorType, enumeratedType))
+ {
+ if (enumerationValidatorType.Constructors.Where(c => c.Parameters.Length == 0).Any())
+ {
+ enumerationValidatorTypeName = enumerationValidatorType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
+ }
+ else
+ {
+ Diag(DiagDescriptors.ValidatorsNeedSimpleConstructor, attrLoc, enumerationValidatorType.Name);
+ }
+ }
+ else
+ {
+ Diag(DiagDescriptors.DoesntImplementIValidateOptions, attrLoc, enumerationValidatorType.Name, enumeratedType.Name);
+ }
+ }
+ else
+ {
+ Diag(DiagDescriptors.NullValidatorType, attrLoc);
+ }
+ }
+ else if (!_visitedModelTypes.Add(enumeratedType.WithNullableAnnotation(NullableAnnotation.None)))
+ {
+ Diag(DiagDescriptors.CircularTypeReferences, attrLoc, enumeratedType.ToString());
+ speculate = false;
+ continue;
+ }
+
+ if (enumerationValidatorTypeName == null)
+ {
+ enumerationValidatorIsSynthetic = true;
+ enumerationValidatorTypeName = AddSynthesizedValidator(enumeratedType, member);
+ }
+
+ // pop the stack
+ _ = _visitedModelTypes.Remove(enumeratedType.WithNullableAnnotation(NullableAnnotation.None));
+ }
+ else if (ConvertTo(attributeType, _symbolHolder.ValidationAttributeSymbol))
+ {
+ var validationAttr = new ValidationAttributeInfo(attributeType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
+ validationAttrs.Add(validationAttr);
+
+ foreach (var constructorArgument in attribute.ConstructorArguments)
+ {
+ validationAttr.ConstructorArguments.Add(GetArgumentExpression(constructorArgument.Type!, constructorArgument.Value));
+ }
+
+ foreach (var namedArgument in attribute.NamedArguments)
+ {
+ validationAttr.Properties.Add(namedArgument.Key, GetArgumentExpression(namedArgument.Value.Type!, namedArgument.Value.Value));
+ }
+ }
+ }
+
+ // generate a warning if the field/property seems like it should be transitively validated
+ if (transValidatorTypeName == null && speculate && memberType.SpecialType == SpecialType.None)
+ {
+ if (!HasOpenGenerics(memberType, out var genericType))
+ {
+ var membersToValidate = GetMembersToValidate(memberType, false);
+ if (membersToValidate.Count > 0)
+ {
+ Diag(DiagDescriptors.PotentiallyMissingTransitiveValidation, member.GetLocation(), memberType.Name, member.Name);
+ }
+ }
+ }
+
+ // generate a warning if the field/property seems like it should be enumerated
+ if (enumerationValidatorTypeName == null && speculate)
+ {
+ var enumeratedType = GetEnumeratedType(memberType);
+ if (enumeratedType is not null)
+ {
+ if (!HasOpenGenerics(enumeratedType, out var genericType))
+ {
+ var membersToValidate = GetMembersToValidate(enumeratedType, false);
+ if (membersToValidate.Count > 0)
+ {
+ Diag(DiagDescriptors.PotentiallyMissingEnumerableValidation, member.GetLocation(), enumeratedType.Name, member.Name);
+ }
+ }
+ }
+ }
+
+ if (validationAttrs.Count > 0 || transValidatorTypeName is not null || enumerationValidatorTypeName is not null)
+ {
+ return new(
+ member.Name,
+ validationAttrs,
+ transValidatorTypeName,
+ transValidatorIsSynthetic,
+ enumerationValidatorTypeName,
+ enumerationValidatorIsSynthetic,
+ memberType.IsReferenceType || memberType.NullableAnnotation == NullableAnnotation.Annotated,
+ memberType.IsValueType,
+ enumeratedIsNullable,
+ enumeratedIsValueType,
+ enumeratedMayBeNull);
+ }
+
+ return null;
+ }
+
+ private string? AddSynthesizedValidator(ITypeSymbol modelType, ISymbol member)
+ {
+ var mt = modelType.WithNullableAnnotation(NullableAnnotation.None);
+ if (mt.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T)
+ {
+ // extract the T from a Nullable<T>
+ mt = ((INamedTypeSymbol)mt).TypeArguments[0];
+ }
+
+ if (_synthesizedValidators.TryGetValue(mt, out var validator))
+ {
+ return "global::" + validator.Namespace + "." + validator.Name;
+ }
+
+ var membersToValidate = GetMembersToValidate(mt, true);
+ if (membersToValidate.Count == 0)
+ {
+ // this type lacks any eligible members
+ Diag(DiagDescriptors.NoEligibleMember, member.GetLocation(), mt.ToString(), member.ToString());
+ return null;
+ }
+
+ var model = new ValidatedModel(
+ GetFQN(mt),
+ mt.Name,
+ false,
+ membersToValidate);
+
+ var validatorTypeName = "__" + mt.Name + "Validator__";
+
+ var result = new ValidatorType(
+ mt.ContainingNamespace.IsGlobalNamespace ? string.Empty : mt.ContainingNamespace.ToString(),
+ validatorTypeName,
+ validatorTypeName,
+ "class",
+ new List<string>(),
+ true,
+ new[] { model });
+
+ _synthesizedValidators[mt] = result;
+ return "global::" + (result.Namespace.Length > 0 ? result.Namespace + "." + result.Name : result.Name);
+ }
+
+ private bool ConvertTo(ITypeSymbol source, ITypeSymbol dest)
+ {
+ var conversion = _compilation.ClassifyConversion(source, dest);
+ return conversion.IsReference && conversion.IsImplicit;
+ }
+
+ private bool ModelSelfValidates(ITypeSymbol modelType)
+ {
+ foreach (var implementingInterface in modelType.AllInterfaces)
+ {
+ if (SymbolEqualityComparer.Default.Equals(implementingInterface.OriginalDefinition, _symbolHolder.IValidatableObjectSymbol))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private List<ITypeSymbol> GetModelTypes(ITypeSymbol validatorType)
+ {
+ var result = new List<ITypeSymbol>();
+ foreach (var implementingInterface in validatorType.AllInterfaces)
+ {
+ if (SymbolEqualityComparer.Default.Equals(implementingInterface.OriginalDefinition, _symbolHolder.ValidateOptionsSymbol))
+ {
+ result.Add(implementingInterface.TypeArguments.First());
+ }
+ }
+
+ return result;
+ }
+
+ private bool CanValidate(ITypeSymbol validatorType, ISymbol modelType)
+ {
+ foreach (var implementingInterface in validatorType.AllInterfaces)
+ {
+ if (SymbolEqualityComparer.Default.Equals(implementingInterface.OriginalDefinition, _symbolHolder.ValidateOptionsSymbol))
+ {
+ var t = implementingInterface.TypeArguments.First();
+ if (SymbolEqualityComparer.Default.Equals(modelType, t))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private string GetArgumentExpression(ITypeSymbol type, object? value)
+ {
+ if (value == null)
+ {
+ return "null";
+ }
+
+ if (type.SpecialType == SpecialType.System_Boolean)
+ {
+ return (bool)value ? "true" : "false";
+ }
+
+ if (SymbolEqualityComparer.Default.Equals(type, _symbolHolder.TypeSymbol) &&
+ value is INamedTypeSymbol sym)
+ {
+ return $"typeof({sym.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)})";
+ }
+
+ if (type.SpecialType == SpecialType.System_String)
+ {
+ return $@"""{EscapeString(value.ToString())}""";
+ }
+
+ if (type.SpecialType == SpecialType.System_Char)
+ {
+ return $@"'{EscapeString(value.ToString())}'";
+ }
+
+ return $"({type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}){Convert.ToString(value, CultureInfo.InvariantCulture)}";
+ }
+
+ private static readonly char[] _specialChars = { '\n', '\r', '"', '\\' };
+
+ private static string EscapeString(string s)
+ {
+ int index = s.IndexOfAny(_specialChars);
+ if (index < 0)
+ {
+ return s;
+ }
+
+ var sb = new StringBuilder(s.Length);
+ _ = sb.Append(s, 0, index);
+
+ while (index < s.Length)
+ {
+ _ = s[index] switch
+ {
+ '\n' => sb.Append("\\n"),
+ '\r' => sb.Append("\\r"),
+ '"' => sb.Append("\\\""),
+ '\\' => sb.Append("\\\\"),
+ var other => sb.Append(other),
+ };
+
+ index++;
+ }
+
+ return sb.ToString();
+ }
+
+ private void Diag(DiagnosticDescriptor desc, Location? location)
+ {
+ _reportDiagnostic(Diagnostic.Create(desc, location, Array.Empty<object?>()));
+ }
+
+ private void Diag(DiagnosticDescriptor desc, Location? location, params object?[]? messageArgs)
+ {
+ _reportDiagnostic(Diagnostic.Create(desc, location, messageArgs));
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Linq;
+using System.Threading;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ internal static class ParserUtilities
+ {
+ internal static AttributeData? GetSymbolAttributeAnnotationOrDefault(ISymbol? attribute, ISymbol symbol)
+ {
+ if (attribute is null)
+ {
+ return null;
+ }
+
+ var attrs = symbol.GetAttributes();
+ foreach (var item in attrs)
+ {
+ if (SymbolEqualityComparer.Default.Equals(attribute, item.AttributeClass) && item.AttributeConstructor != null)
+ {
+ return item;
+ }
+ }
+
+ return null;
+ }
+
+ internal static bool PropertyHasModifier(ISymbol property, SyntaxKind modifierToSearch, CancellationToken token)
+ => property
+ .DeclaringSyntaxReferences
+ .Any(x =>
+ x.GetSyntax(token) is PropertyDeclarationSyntax syntax &&
+ syntax.Modifiers.Any(m => m.IsKind(modifierToSearch)));
+
+ internal static Location? GetLocation(this ISymbol symbol)
+ {
+ if (symbol is null)
+ {
+ return null;
+ }
+
+ return symbol.Locations.IsDefaultOrEmpty
+ ? null
+ : symbol.Locations[0];
+ }
+
+ internal static bool IsBaseOrIdentity(ITypeSymbol source, ITypeSymbol dest, Compilation comp)
+ {
+ var conversion = comp.ClassifyConversion(source, dest);
+ return conversion.IsIdentity || (conversion.IsReference && conversion.IsImplicit);
+ }
+
+ internal static bool ImplementsInterface(this ITypeSymbol type, ITypeSymbol interfaceType)
+ {
+ foreach (var iface in type.AllInterfaces)
+ {
+ if (SymbolEqualityComparer.Default.Equals(interfaceType, iface))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // Check if parameter has either simplified (i.e. "int?") or explicit (Nullable<int>) nullable type declaration:
+ internal static bool IsNullableOfT(this ITypeSymbol type)
+ => type.SpecialType == SpecialType.System_Nullable_T || type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="AlreadyImplementsValidateMethodMessage" xml:space="preserve">
+ <value>Type {0} already implements the Validate method.</value>
+ </data>
+ <data name="AlreadyImplementsValidateMethodTitle" xml:space="preserve">
+ <value>A type already includes an implementation of the 'Validate' method.</value>
+ </data>
+ <data name="CantBeStaticClassMessage" xml:space="preserve">
+ <value>[OptionsValidator] cannot be applied to static class {0}.</value>
+ </data>
+ <data name="CantBeStaticClassTitle" xml:space="preserve">
+ <value>'OptionsValidatorAttribute' can't be applied to a static class.</value>
+ </data>
+ <data name="CantUseWithGenericTypesMessage" xml:space="preserve">
+ <value>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</value>
+ </data>
+ <data name="CantUseWithGenericTypesTitle" xml:space="preserve">
+ <value>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</value>
+ </data>
+ <data name="CircularTypeReferencesMessage" xml:space="preserve">
+ <value>There is a circular type reference involving type {0} preventing it from being used for static validation.</value>
+ </data>
+ <data name="CircularTypeReferencesTitle" xml:space="preserve">
+ <value>Unsupported circular references in model types.</value>
+ </data>
+ <data name="DoesntImplementIValidateOptionsMessage" xml:space="preserve">
+ <value>Type {0} does not implement the required IValidateOptions<{1}> interface.</value>
+ </data>
+ <data name="DoesntImplementIValidateOptionsTitle" xml:space="preserve">
+ <value>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</value>
+ </data>
+ <data name="MemberIsInaccessibleMessage" xml:space="preserve">
+ <value>Can't apply validation attributes to private field or property {0}.</value>
+ </data>
+ <data name="MemberIsInaccessibleTitle" xml:space="preserve">
+ <value>Can't validate private fields or properties.</value>
+ </data>
+ <data name="NoEligibleMemberMessage" xml:space="preserve">
+ <value>Type {0} has no fields or properties to validate, referenced from member {1}.</value>
+ </data>
+ <data name="NoEligibleMembersFromValidatorMessage" xml:space="preserve">
+ <value>Type {0} has no fields or properties to validate, referenced by type {1}.</value>
+ </data>
+ <data name="NoEligibleMembersFromValidatorTitle" xml:space="preserve">
+ <value>A type has no fields or properties to validate.</value>
+ </data>
+ <data name="NoEligibleMemberTitle" xml:space="preserve">
+ <value>A member type has no fields or properties to validate.</value>
+ </data>
+ <data name="NotEnumerableTypeMessage" xml:space="preserve">
+ <value>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</value>
+ </data>
+ <data name="NotEnumerableTypeTitle" xml:space="preserve">
+ <value>Member type is not enumerable.</value>
+ </data>
+ <data name="NullValidatorTypeMessage" xml:space="preserve">
+ <value>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</value>
+ </data>
+ <data name="NullValidatorTypeTitle" xml:space="preserve">
+ <value>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</value>
+ </data>
+ <data name="PotentiallyMissingEnumerableValidationMessage" xml:space="preserve">
+ <value>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</value>
+ </data>
+ <data name="PotentiallyMissingEnumerableValidationTitle" xml:space="preserve">
+ <value>Member potentially missing enumerable validation.</value>
+ </data>
+ <data name="PotentiallyMissingTransitiveValidationMessage" xml:space="preserve">
+ <value>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</value>
+ </data>
+ <data name="PotentiallyMissingTransitiveValidationTitle" xml:space="preserve">
+ <value>Member potentially missing transitive validation.</value>
+ </data>
+ <data name="ValidatorsNeedSimpleConstructorMessage" xml:space="preserve">
+ <value>Validator type {0} doesn't have a parameterless constructor.</value>
+ </data>
+ <data name="ValidatorsNeedSimpleConstructorTitle" xml:space="preserve">
+ <value>Validators used for transitive or enumerable validation must have a constructor with no parameters.</value>
+ </data>
+</root>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="cs" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="de" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="es" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="fr" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="it" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="ja" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="ko" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="pl" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="pt-BR" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="ru" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="tr" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="zh-Hans" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
+ <file datatype="xml" source-language="en" target-language="zh-Hant" original="../Strings.resx">
+ <body>
+ <trans-unit id="AlreadyImplementsValidateMethodMessage">
+ <source>Type {0} already implements the Validate method.</source>
+ <target state="new">Type {0} already implements the Validate method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="AlreadyImplementsValidateMethodTitle">
+ <source>A type already includes an implementation of the 'Validate' method.</source>
+ <target state="new">A type already includes an implementation of the 'Validate' method.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassMessage">
+ <source>[OptionsValidator] cannot be applied to static class {0}.</source>
+ <target state="new">[OptionsValidator] cannot be applied to static class {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantBeStaticClassTitle">
+ <source>'OptionsValidatorAttribute' can't be applied to a static class.</source>
+ <target state="new">'OptionsValidatorAttribute' can't be applied to a static class.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesMessage">
+ <source>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</source>
+ <target state="new">Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CantUseWithGenericTypesTitle">
+ <source>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</source>
+ <target state="new">Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesMessage">
+ <source>There is a circular type reference involving type {0} preventing it from being used for static validation.</source>
+ <target state="new">There is a circular type reference involving type {0} preventing it from being used for static validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="CircularTypeReferencesTitle">
+ <source>Unsupported circular references in model types.</source>
+ <target state="new">Unsupported circular references in model types.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsMessage">
+ <source>Type {0} does not implement the required IValidateOptions<{1}> interface.</source>
+ <target state="new">Type {0} does not implement the required IValidateOptions<{1}> interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="DoesntImplementIValidateOptionsTitle">
+ <source>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</source>
+ <target state="new">A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleMessage">
+ <source>Can't apply validation attributes to private field or property {0}.</source>
+ <target state="new">Can't apply validation attributes to private field or property {0}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MemberIsInaccessibleTitle">
+ <source>Can't validate private fields or properties.</source>
+ <target state="new">Can't validate private fields or properties.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberMessage">
+ <source>Type {0} has no fields or properties to validate, referenced from member {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced from member {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMemberTitle">
+ <source>A member type has no fields or properties to validate.</source>
+ <target state="new">A member type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorMessage">
+ <source>Type {0} has no fields or properties to validate, referenced by type {1}.</source>
+ <target state="new">Type {0} has no fields or properties to validate, referenced by type {1}.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NoEligibleMembersFromValidatorTitle">
+ <source>A type has no fields or properties to validate.</source>
+ <target state="new">A type has no fields or properties to validate.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeMessage">
+ <source>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</source>
+ <target state="new">[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NotEnumerableTypeTitle">
+ <source>Member type is not enumerable.</source>
+ <target state="new">Member type is not enumerable.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeMessage">
+ <source>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</source>
+ <target state="new">Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="NullValidatorTypeTitle">
+ <source>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</source>
+ <target state="new">Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingEnumerableValidationTitle">
+ <source>Member potentially missing enumerable validation.</source>
+ <target state="new">Member potentially missing enumerable validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationMessage">
+ <source>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</source>
+ <target state="new">Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="PotentiallyMissingTransitiveValidationTitle">
+ <source>Member potentially missing transitive validation.</source>
+ <target state="new">Member potentially missing transitive validation.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorMessage">
+ <source>Validator type {0} doesn't have a parameterless constructor.</source>
+ <target state="new">Validator type {0} doesn't have a parameterless constructor.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="ValidatorsNeedSimpleConstructorTitle">
+ <source>Validators used for transitive or enumerable validation must have a constructor with no parameters.</source>
+ <target state="new">Validators used for transitive or enumerable validation must have a constructor with no parameters.</target>
+ <note />
+ </trans-unit>
+ </body>
+ </file>
+</xliff>
\ No newline at end of file
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.CodeAnalysis;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ /// <summary>
+ /// Holds required symbols for the <see cref="Generator"/>.
+ /// </summary>
+ internal sealed record class SymbolHolder(
+ INamedTypeSymbol OptionsValidatorSymbol,
+ INamedTypeSymbol ValidationAttributeSymbol,
+ INamedTypeSymbol DataTypeAttributeSymbol,
+ INamedTypeSymbol ValidateOptionsSymbol,
+ INamedTypeSymbol IValidatableObjectSymbol,
+ INamedTypeSymbol TypeSymbol,
+ INamedTypeSymbol? ValidateObjectMembersAttributeSymbol,
+ INamedTypeSymbol? ValidateEnumeratedItemsAttributeSymbol);
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.CodeAnalysis;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ internal static class SymbolLoader
+ {
+ public const string OptionsValidatorAttribute = "Microsoft.Extensions.Options.OptionsValidatorAttribute";
+ internal const string ValidationAttribute = "System.ComponentModel.DataAnnotations.ValidationAttribute";
+ internal const string DataTypeAttribute = "System.ComponentModel.DataAnnotations.DataTypeAttribute";
+ internal const string IValidatableObjectType = "System.ComponentModel.DataAnnotations.IValidatableObject";
+ internal const string IValidateOptionsType = "Microsoft.Extensions.Options.IValidateOptions`1";
+ internal const string TypeOfType = "System.Type";
+ internal const string ValidateObjectMembersAttribute = "Microsoft.Extensions.Options.ValidateObjectMembersAttribute";
+ internal const string ValidateEnumeratedItemsAttribute = "Microsoft.Extensions.Options.ValidateEnumeratedItemsAttribute";
+
+ public static bool TryLoad(Compilation compilation, out SymbolHolder? symbolHolder)
+ {
+ INamedTypeSymbol? GetSymbol(string metadataName, bool optional = false)
+ {
+ var symbol = compilation.GetTypeByMetadataName(metadataName);
+ if (symbol == null && !optional)
+ {
+ return null;
+ }
+
+ return symbol;
+ }
+
+ // required
+ var optionsValidatorSymbol = GetSymbol(OptionsValidatorAttribute);
+ var validationAttributeSymbol = GetSymbol(ValidationAttribute);
+ var dataTypeAttributeSymbol = GetSymbol(DataTypeAttribute);
+ var ivalidatableObjectSymbol = GetSymbol(IValidatableObjectType);
+ var validateOptionsSymbol = GetSymbol(IValidateOptionsType);
+ var typeSymbol = GetSymbol(TypeOfType);
+
+ #pragma warning disable S1067 // Expressions should not be too complex
+ if (optionsValidatorSymbol == null ||
+ validationAttributeSymbol == null ||
+ dataTypeAttributeSymbol == null ||
+ ivalidatableObjectSymbol == null ||
+ validateOptionsSymbol == null ||
+ typeSymbol == null)
+ {
+ symbolHolder = default;
+ return false;
+ }
+ #pragma warning restore S1067 // Expressions should not be too complex
+
+ symbolHolder = new(
+ optionsValidatorSymbol,
+ validationAttributeSymbol,
+ dataTypeAttributeSymbol,
+ validateOptionsSymbol,
+ ivalidatableObjectSymbol,
+ typeSymbol,
+
+ // optional
+ GetSymbol(ValidateObjectMembersAttribute, optional: true),
+ GetSymbol(ValidateEnumeratedItemsAttribute, optional: true));
+
+ return true;
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace Microsoft.Extensions.Options.Generators
+{
+ /// <summary>
+ /// Class/struct/record declaration syntax receiver for generators.
+ /// </summary>
+ internal sealed class TypeDeclarationSyntaxReceiver : ISyntaxReceiver
+ {
+ internal static ISyntaxReceiver Create() => new TypeDeclarationSyntaxReceiver();
+
+ /// <summary>
+ /// Gets class/struct/record declaration syntax holders after visiting nodes.
+ /// </summary>
+ public ICollection<TypeDeclarationSyntax> TypeDeclarations { get; } = new List<TypeDeclarationSyntax>();
+
+ /// <inheritdoc/>
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
+ {
+ if (syntaxNode is ClassDeclarationSyntax classSyntax)
+ {
+ TypeDeclarations.Add(classSyntax);
+ }
+ else if (syntaxNode is StructDeclarationSyntax structSyntax)
+ {
+ TypeDeclarations.Add(structSyntax);
+ }
+ else if (syntaxNode is RecordDeclarationSyntax recordSyntax)
+ {
+ TypeDeclarations.Add(recordSyntax);
+ }
+ else if (syntaxNode is InterfaceDeclarationSyntax interfaceSyntax)
+ {
+ TypeDeclarations.Add(interfaceSyntax);
+ }
+ }
+ }
+}
public string OptionsName { get { throw null; } }
public System.Type OptionsType { get { throw null; } }
}
+ [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct)]
+ public sealed class OptionsValidatorAttribute : System.Attribute
+ {
+ }
public partial class OptionsWrapper<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TOptions> : Microsoft.Extensions.Options.IOptions<TOptions> where TOptions : class
{
public OptionsWrapper(TOptions options) { }
public virtual void PostConfigure(string? name, TOptions options) { }
public void PostConfigure(TOptions options) { }
}
+ [System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.Field)]
+ public sealed class ValidateEnumeratedItemsAttribute : System.Attribute
+ {
+ public ValidateEnumeratedItemsAttribute() {}
+ public ValidateEnumeratedItemsAttribute(System.Type validator) { throw null; }
+ public System.Type? Validator { get {throw null; } }
+ }
+ [System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.Field)]
+ public sealed class ValidateObjectMembersAttribute : System.Attribute
+ {
+ public ValidateObjectMembersAttribute() {}
+ public ValidateObjectMembersAttribute(System.Type validator) { throw null; }
+ public System.Type? Validator { get { throw null; } }
+ }
public partial class ValidateOptionsResult
{
public static readonly Microsoft.Extensions.Options.ValidateOptionsResult Skip;
<Reference Include="System.ComponentModel.DataAnnotations" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\gen\Microsoft.Extensions.Options.SourceGeneration.csproj"
+ ReferenceOutputAssembly="false"
+ PackAsAnalyzer="true" />
+ </ItemGroup>
+
</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Diagnostics;
+
+namespace Microsoft.Extensions.Options
+{
+ /// <summary>
+ /// Triggers the automatic generation of the implementation of <see cref="Microsoft.Extensions.Options.IValidateOptions{T}" /> at compile time.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
+ public sealed class OptionsValidatorAttribute : Attribute
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.Extensions.Options
+{
+ /// <summary>
+ /// Marks a field or property to be enumerated, and each enumerated object to be validated.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
+ public sealed class ValidateEnumeratedItemsAttribute : Attribute
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidateEnumeratedItemsAttribute"/> class.
+ /// </summary>
+ /// <remarks>
+ /// Using this constructor for a field/property tells the code generator to
+ /// generate validation for the individual members of the enumerable's type.
+ /// </remarks>
+ public ValidateEnumeratedItemsAttribute()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidateEnumeratedItemsAttribute"/> class.
+ /// </summary>
+ /// <param name="validator">A type that implements <see cref="IValidateOptions{T}" /> for the enumerable's type.</param>
+ /// <remarks>
+ /// Using this constructor for a field/property tells the code generator to use the given type to validate
+ /// the object held by the enumerable.
+ /// </remarks>
+ public ValidateEnumeratedItemsAttribute(Type validator)
+ {
+ Validator = validator;
+ }
+
+ /// <summary>
+ /// Gets the type to use to validate the enumerable's objects.
+ /// </summary>
+ public Type? Validator { get; }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.Extensions.Options
+{
+ /// <summary>
+ /// Marks a field or property to be validated transitively.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
+ public sealed class ValidateObjectMembersAttribute : Attribute
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidateObjectMembersAttribute"/> class.
+ /// </summary>
+ /// <remarks>
+ /// Using this constructor for a field/property tells the code generator to
+ /// generate validation for the individual members of the field/property's type.
+ /// </remarks>
+ public ValidateObjectMembersAttribute()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ValidateObjectMembersAttribute"/> class.
+ /// </summary>
+ /// <param name="validator">A type that implements <see cref="IValidateOptions{T}" /> for the field/property's type.</param>
+ /// <remarks>
+ /// Using this constructor for a field/property tells the code generator to use the given type to validate
+ /// the object held by the field/property.
+ /// </remarks>
+ public ValidateObjectMembersAttribute(Type validator)
+ {
+ Validator = validator;
+ }
+
+ /// <summary>
+ /// Gets the type to use to validate a field or property.
+ /// </summary>
+ public Type? Validator { get; }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Options.Generators;
+using SourceGenerators.Tests;
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.ComponentModel.DataAnnotations;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Unit.Test;
+
+public class EmitterTests
+{
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task TestEmitterWithCustomValidator()
+ {
+ string source = """
+ using System;
+ using System.ComponentModel.DataAnnotations;
+ using Microsoft.Extensions.Options;
+
+ #nullable enable
+
+ namespace HelloWorld
+ {
+ public class MyOptions
+ {
+ [Required]
+ public string Val1 { get; set; } = string.Empty;
+
+ [Range(1, 3)]
+ public int Val2 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial struct MyOptionsValidator : IValidateOptions<MyOptions>
+ {
+ }
+ }
+ """;
+
+ string generatedSource = """
+
+ // <auto-generated/>
+ #nullable enable
+ #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103
+ namespace HelloWorld
+{
+ partial struct MyOptionsValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::HelloWorld.MyOptions options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "MyOptions" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val1";
+ context.DisplayName = baseName + "Val1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val2";
+ context.DisplayName = baseName + "Val2";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace __OptionValidationStaticInstances
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal static class __Attributes
+ {
+ internal static readonly global::System.ComponentModel.DataAnnotations.RequiredAttribute A1 = new global::System.ComponentModel.DataAnnotations.RequiredAttribute();
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A2 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)1,
+ (int)3);
+ }
+}
+namespace __OptionValidationStaticInstances
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal static class __Validators
+ {
+ }
+}
+
+""";
+
+ var (diagnostics, generatedSources) = await RoslynTestUtils.RunGenerator(
+ new Generator(),
+ new[]
+ {
+ Assembly.GetAssembly(typeof(RequiredAttribute))!,
+ Assembly.GetAssembly(typeof(OptionsValidatorAttribute))!,
+ Assembly.GetAssembly(typeof(IValidateOptions<object>))!,
+ },
+ new List<string> { source })
+ .ConfigureAwait(false);
+
+ Assert.Empty(diagnostics);
+ _ = Assert.Single(generatedSources);
+
+ Assert.Equal(generatedSource.Replace("\r\n", "\n"), generatedSources[0].SourceText.ToString().Replace("\r\n", "\n"));
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task PotentiallyMissingAttributes()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [Required]
+ public SecondModel? P1 { get; set; }
+
+ [Required]
+ public System.Collections.Generic.IList<SecondModel>? P2 { get; set; }
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ public string? P3;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+ ");
+
+ Assert.Equal(2, diagnostics.Count);
+ Assert.Equal(DiagDescriptors.PotentiallyMissingTransitiveValidation.Id, diagnostics[0].Id);
+ Assert.Equal(DiagDescriptors.PotentiallyMissingEnumerableValidation.Id, diagnostics[1].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task CircularTypeReferences()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [Required]
+ [ValidateObjectMembers]
+ public FirstModel? P1 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+ ");
+
+ _ = Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.CircularTypeReferences.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task InvalidValidatorInterface()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [Required]
+ public string? P1;
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ public string? P2;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class SecondValidator
+ {
+ }
+ ");
+
+ _ = Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task NotValidator()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [ValidateObjectMembers(typeof(SecondValidator)]
+ public SecondModel? P1;
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ public string? P2;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+
+ public partial class SecondValidator
+ {
+ }
+ ");
+
+ _ = Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ValidatorAlreadyImplementValidateFunction()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [Required]
+ public string? P1;
+
+ [ValidateObjectMembers(typeof(SecondValidator)]
+ public SecondModel? P2;
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ public string? P3;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class SecondValidator : IValidateOptions<SecondModel>
+ {
+ public ValidateOptionsResult Validate(string name, SecondModel options)
+ {
+ throw new System.NotSupportedException();
+ }
+ }
+ ");
+
+ _ = Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.AlreadyImplementsValidateMethod.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task NullValidator()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [ValidateObjectMembers(null!)]
+ public SecondModel? P1;
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ public string? P2;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class SecondValidator : IValidateOptions<SecondModel>
+ {
+ }
+ ");
+
+ _ = Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.NullValidatorType.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task NoSimpleValidatorConstructor()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [Required]
+ public string? P1;
+
+ [ValidateObjectMembers(typeof(SecondValidator)]
+ public SecondModel? P2;
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ public string? P3;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class SecondValidator : IValidateOptions<SecondModel>
+ {
+ public SecondValidator(int _)
+ {
+ }
+ }
+ ");
+
+ _ = Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.ValidatorsNeedSimpleConstructor.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task NoStaticValidator()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [Required]
+ public string P1;
+ }
+
+ [OptionsValidator]
+ public static partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+ ");
+
+ _ = Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.CantBeStaticClass.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task BogusModelType()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<Bogus>
+ {
+ }
+ ");
+
+ // the generator doesn't produce any errors here, since the C# compiler will take care of it
+ Assert.Empty(diagnostics);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task CantValidateOpenGenericMembers()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel<T>
+ {
+ [Required]
+ [ValidateObjectMembers]
+ public T? P1;
+
+ [ValidateObjectMembers]
+ [Required]
+ public T[]? P2;
+
+ [ValidateObjectMembers]
+ [Required]
+ public System.Collections.Generics.IList<T> P3 = null!;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator<T> : IValidateOptions<FirstModel<T>>
+ {
+ }
+ ");
+
+ Assert.Equal(3, diagnostics.Count);
+ Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, diagnostics[0].Id);
+ Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, diagnostics[1].Id);
+ Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, diagnostics[2].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ClosedGenerics()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel<T>
+ {
+ [Required]
+ [ValidateObjectMembers]
+ public T? P1;
+
+ [ValidateObjectMembers]
+ [Required]
+ public T[]? P2;
+
+ [ValidateObjectMembers]
+ [Required]
+ public int[]? P3;
+
+ [ValidateObjectMembers]
+ [Required]
+ public System.Collections.Generics.IList<T>? P4;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel<string>>
+ {
+ }
+ ");
+
+ Assert.Equal(4, diagnostics.Count);
+ Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[0].Id);
+ Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[1].Id);
+ Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[2].Id);
+ Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[3].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task NoEligibleMembers()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [Required]
+ [ValidateObjectMembers]
+ public SecondModel? P1;
+ }
+
+ public class SecondModel
+ {
+ public string P2;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class SecondValidator : IValidateOptions<SecondModel>
+ {
+ }
+ ");
+
+ Assert.Equal(2, diagnostics.Count);
+ Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[0].Id);
+ Assert.Equal(DiagDescriptors.NoEligibleMembersFromValidator.Id, diagnostics[1].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task AlreadyImplemented()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [Required]
+ public string One { get; set; } = string.Empty;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ public void Validate(string name, FirstModel fm)
+ {
+ }
+ }
+ ");
+
+ _ = Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.AlreadyImplementsValidateMethod.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldNotProduceInfoWhenTheClassHasABaseClass()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class Parent
+ {
+ [Required]
+ public string parentString { get; set; }
+ }
+
+ public class Child : Parent
+ {
+ [Required]
+ public string childString { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<Child>
+ {
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldNotProduceInfoWhenTransitiveClassHasABaseClass()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class Parent
+ {
+ [Required]
+ public string parentString { get; set; }
+ }
+
+ public class Child : Parent
+ {
+ [Required]
+ public string childString { get; set; }
+ }
+
+ public class MyOptions
+ {
+ [ValidateObjectMembers]
+ public Child childVal { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<MyOptions>
+ {
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ [InlineData("bool")]
+ [InlineData("int")]
+ [InlineData("double")]
+ [InlineData("string")]
+ [InlineData("System.String")]
+ [InlineData("System.DateTime")]
+ public async Task ShouldProduceWarn_WhenTransitiveAttrMisused(string memberClass)
+ {
+ var (diagnostics, _) = await RunGenerator(@$"
+ public class InnerModel
+ {{
+ [Required]
+ public string childString {{ get; set; }}
+ }}
+
+ public class MyOptions
+ {{
+ [Required]
+ public string simpleVal {{ get; set; }}
+
+ [ValidateObjectMembers]
+ public {memberClass} complexVal {{ get; set; }}
+ }}
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<MyOptions>
+ {{
+ }}
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldProduceWarningWhenTheClassHasNoEligibleMembers()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class Child
+ {
+ private string AccountName { get; set; }
+ public object Weight;
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<Child>
+ {
+ }
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.NoEligibleMembersFromValidator.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ [InlineData("private")]
+ [InlineData("protected")]
+ public async Task ShouldProduceWarningWhenTheClassMembersAreInaccessible(string accessModifier)
+ {
+ var (diagnostics, _) = await RunGenerator($@"
+ public class Model
+ {{
+ [Required]
+ public string? PublicVal {{ get; set; }}
+
+ [Required]
+ {accessModifier} string? Val {{ get; set; }}
+ }}
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<Model>
+ {{
+ }}
+ ");
+
+ Assert.Single(diagnostics);
+ Assert.Equal("SYSLIB1206", diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldNotProduceErrorWhenMultipleValidationAnnotationsExist()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class IValidateOptionsTestFile
+ {
+ [MinLength(5)]
+ [MaxLength(15)]
+ public string Val9 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<IValidateOptionsTestFile>
+ {
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldNotProduceErrorWhenDataTypeAttributesAreUsed()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class IValidateOptionsTestFile
+ {
+ [CreditCard]
+ public string Val3 = """";
+
+ [EmailAddress]
+ public string Val6 { get; set; }
+
+ [EnumDataType(typeof(string))]
+ public string Val7 { get; set; }
+
+ [FileExtensions]
+ public string Val8 { get; set; }
+
+ [Phone]
+ public string Val10 { get; set; }
+
+ [Url]
+ public string Val11 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<IValidateOptionsTestFile>
+ {
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldNotProduceErrorWhenConstVariableIsUsedAsAttributeArgument()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class IValidateOptionsTestFile
+ {
+ private const int q = 5;
+ [Range(q, 10)]
+ public string Val11 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<IValidateOptionsTestFile>
+ {
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
+ // Testing on all existing & eligible annotations extending ValidationAttribute that aren't used above
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldNotProduceAnyMessagesWhenExistingValidationsArePlaced()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class IValidateOptionsTestFile
+ {
+ [Required]
+ public string Val { get; set; }
+
+ [Compare(""val"")]
+ public string Val2 { get; set; }
+
+ [DataType(DataType.Password)]
+ public string _val5 = """";
+
+ [Range(5.1, 10.11)]
+ public string Val12 { get; set; }
+
+ [Range(typeof(MemberDeclarationSyntax), ""1/2/2004"", ""3/4/2004"")]
+ public string Val14 { get; set; }
+
+ [RegularExpression("""")]
+ public string Val15 { get; set; }
+
+ [StringLength(5)]
+ public string Val16 { get; set; }
+
+ [CustomValidation(typeof(MemberDeclarationSyntax), ""CustomMethod"")]
+ public string Val17 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<IValidateOptionsTestFile>
+ {
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldNotProduceErrorWhenPropertiesAreUsedAsAttributeArgument()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class IValidateOptionsTestFile
+ {
+ private const int q = 5;
+ [Range(q, 10, ErrorMessage = ""ErrorMessage"")]
+ public string Val11 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<IValidateOptionsTestFile>
+ {
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldSkipWhenOptionsValidatorAttributeDoesNotExist()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class IValidateOptionsTestFile
+ {
+ private const int q = 5;
+ [Range(q, 10, ErrorMessage = ""ErrorMessage"")]
+ public string Val11 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<IValidateOptionsTestFile>
+ {
+ }
+ ", includeOptionValidatorReferences: false);
+
+ Assert.Empty(diagnostics);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldSkipAtrributeWhenAttributeSymbolCannotBeFound()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class IValidateOptionsTestFile
+ {
+ [RandomTest]
+ public string Val11 { get; set; }
+
+ [Range(1, 10, ErrorMessage = ""ErrorMessage"")]
+ public string Val12 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<IValidateOptionsTestFile>
+ {
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldSkipAtrributeWhenAttributeSymbolIsNotBasedOnValidationAttribute()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class IValidateOptionsTestFile
+ {
+ [FilterUIHint(""MultiForeignKey"")]
+ public string Val11 { get; set; }
+
+ [Range(1, 10, ErrorMessage = ""ErrorMessage"")]
+ public string Val12 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<IValidateOptionsTestFile>
+ {
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldAcceptAtrributeWhenAttributeIsInDifferentNamespace()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ namespace Test {
+ public class IValidateOptionsTestFile
+ {
+ [Test]
+ public string Val11 { get; set; }
+ }
+
+ [AttributeUsage(AttributeTargets.Class)]
+ public sealed class TestAttribute : ValidationAttribute
+ {
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<IValidateOptionsTestFile>
+ {
+ }
+ }
+ ", inNamespace: false);
+
+ Assert.Empty(diagnostics);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldHandleAtrributePropertiesOtherThanString()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ namespace Test {
+ public class IValidateOptionsTestFile
+ {
+ [Test(num = 5)]
+ public string Val11 { get; set; }
+
+ [Required]
+ public string Val12 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<IValidateOptionsTestFile>
+ {
+ }
+ }
+
+ namespace System.ComponentModel.DataAnnotations {
+ [AttributeUsage(AttributeTargets.Class)]
+ public sealed class TestAttribute : ValidationAttribute
+ {
+ public int num { get; set; }
+ public TestAttribute() {
+ }
+ }
+ }
+ ", inNamespace: false);
+
+ Assert.Empty(diagnostics);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ShouldStoreFloatValuesCorrectly()
+ {
+ var backupCulture = CultureInfo.CurrentCulture;
+ CultureInfo.CurrentCulture = new CultureInfo("ru-RU", false);
+ try
+ {
+ var (diagMessages, generatedResults) = await RunGenerator(@"
+ public class Model
+ {
+ [Range(-0.1, 1.3)]
+ public string Val { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class Validator : IValidateOptions<Model>
+ {
+ }
+ ");
+
+ Assert.Empty(diagMessages);
+ Assert.Single(generatedResults);
+ Assert.DoesNotContain("0,1", generatedResults[0].SourceText.ToString());
+ Assert.DoesNotContain("1,3", generatedResults[0].SourceText.ToString());
+ }
+ finally
+ {
+ CultureInfo.CurrentCulture = backupCulture;
+ }
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task MultiModelValidatorGeneratesOnlyOnePartialTypeBlock()
+ {
+ var (diagnostics, sources) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [Required]
+ public string P1 { get; set; }
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ public string P2 { get; set; }
+ }
+
+ public class ThirdModel
+ {
+ [Required]
+ public string P3 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class MultiValidator : IValidateOptions<FirstModel>, IValidateOptions<SecondModel>, IValidateOptions<ThirdModel>
+ {
+ }
+ ");
+
+ var typeDeclarations = sources[0].SyntaxTree
+ .GetRoot()
+ .DescendantNodes()
+ .OfType<TypeDeclarationSyntax>()
+ .ToArray();
+
+ var multiValidatorTypeDeclarations = typeDeclarations
+ .Where(x => x.Identifier.ValueText == "MultiValidator")
+ .ToArray();
+
+ Assert.Single(multiValidatorTypeDeclarations);
+
+ var validateMethodDeclarations = multiValidatorTypeDeclarations[0]
+ .DescendantNodes()
+ .OfType<MethodDeclarationSyntax>()
+ .Where(x => x.Identifier.ValueText == "Validate")
+ .ToArray();
+
+ Assert.Equal(3, validateMethodDeclarations.Length);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task CircularTypeReferencesInEnumeration()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [Required]
+ [ValidateEnumeratedItems]
+ public FirstModel[]? P1 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+ ");
+
+ _ = Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.CircularTypeReferences.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task NotValidatorInEnumeration()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [ValidateEnumeratedItems(typeof(SecondValidator)]
+ public SecondModel[]? P1;
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ public string? P2;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+
+ public partial class SecondValidator
+ {
+ }
+ ");
+
+ _ = Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.DoesntImplementIValidateOptions.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task NullValidatorInEnumeration()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [ValidateEnumeratedItems(null!)]
+ public SecondModel[]? P1;
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ public string? P2;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class SecondValidator : IValidateOptions<SecondModel>
+ {
+ }
+ ");
+
+ _ = Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.NullValidatorType.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task NoSimpleValidatorConstructorInEnumeration()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [Required]
+ public string? P1;
+
+ [ValidateEnumeratedItems(typeof(SecondValidator)]
+ public SecondModel[]? P2;
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ public string? P3;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class SecondValidator : IValidateOptions<SecondModel>
+ {
+ public SecondValidator(int _)
+ {
+ }
+ }
+ ");
+
+ _ = Assert.Single(diagnostics);
+ Assert.Equal(DiagDescriptors.ValidatorsNeedSimpleConstructor.Id, diagnostics[0].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task CantValidateOpenGenericMembersInEnumeration()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel<T>
+ {
+ [Required]
+ [ValidateEnumeratedItems]
+ public T[]? P1;
+
+ [ValidateEnumeratedItems]
+ [Required]
+ public T[]? P2;
+
+ [ValidateEnumeratedItems]
+ [Required]
+ public System.Collections.Generic.IList<T> P3 = null!;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator<T> : IValidateOptions<FirstModel<T>>
+ {
+ }
+ ");
+
+ Assert.Equal(3, diagnostics.Count);
+ Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, diagnostics[0].Id);
+ Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, diagnostics[1].Id);
+ Assert.Equal(DiagDescriptors.CantUseWithGenericTypes.Id, diagnostics[2].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task ClosedGenericsInEnumeration()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel<T>
+ {
+ [ValidateEnumeratedItems]
+ [Required]
+ public T[]? P1;
+
+ [ValidateEnumeratedItems]
+ [Required]
+ public int[]? P2;
+
+ [ValidateEnumeratedItems]
+ [Required]
+ public System.Collections.Generic.IList<T>? P3;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel<string>>
+ {
+ }
+ ");
+
+ Assert.Equal(3, diagnostics.Count);
+ Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[0].Id);
+ Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[1].Id);
+ Assert.Equal(DiagDescriptors.NoEligibleMember.Id, diagnostics[2].Id);
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task NotEnumerable()
+ {
+ var (diagnostics, _) = await RunGenerator(@"
+ public class FirstModel
+ {
+ [Required]
+ [ValidateEnumeratedItems]
+ public int P1;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+ ");
+
+ Assert.Equal(1, diagnostics.Count);
+ Assert.Equal(DiagDescriptors.NotEnumerableType.Id, diagnostics[0].Id);
+ }
+
+ private static async Task<(IReadOnlyList<Diagnostic> diagnostics, ImmutableArray<GeneratedSourceResult> generatedSources)> RunGenerator(
+ string code,
+ bool wrap = true,
+ bool inNamespace = true,
+ bool includeOptionValidatorReferences = true,
+ bool includeSystemReferences = true,
+ bool includeOptionsReferences = true,
+ bool includeTransitiveReferences = true)
+ {
+ var text = code;
+ if (wrap)
+ {
+ var nspaceStart = "namespace Test {";
+ var nspaceEnd = "}";
+ if (!inNamespace)
+ {
+ nspaceStart = "";
+ nspaceEnd = "";
+ }
+
+ text = $@"
+ {nspaceStart}
+ using System.ComponentModel.DataAnnotations;
+ using Microsoft.Extensions.Options.Validation;
+ using Microsoft.Shared.Data.Validation;
+ using Microsoft.Extensions.Options;
+ using Microsoft.CodeAnalysis.CSharp.Syntax;
+ {code}
+ {nspaceEnd}
+ ";
+ }
+
+ var assemblies = new List<Assembly> { Assembly.GetAssembly(typeof(MemberDeclarationSyntax))! };
+
+ if (includeOptionValidatorReferences)
+ {
+ assemblies.Add(Assembly.GetAssembly(typeof(OptionsValidatorAttribute))!);
+ }
+
+ if (includeSystemReferences)
+ {
+ assemblies.Add(Assembly.GetAssembly(typeof(RequiredAttribute))!);
+ }
+
+ if (includeOptionsReferences)
+ {
+ assemblies.Add(Assembly.GetAssembly(typeof(IValidateOptions<object>))!);
+ }
+
+ if (includeTransitiveReferences)
+ {
+ assemblies.Add(Assembly.GetAssembly(typeof(Microsoft.Extensions.Options.ValidateObjectMembersAttribute))!);
+ }
+
+ var result = await RoslynTestUtils.RunGenerator(new Generator(), assemblies.ToArray(), new[] { text })
+ .ConfigureAwait(false);
+
+ return result;
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFrameworks>$(NetCoreAppCurrent);$(NetFrameworkMinimum)</TargetFrameworks>
+ <RoslynApiVersion>$(MicrosoftCodeAnalysisVersion_4_4)</RoslynApiVersion>
+ <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
+ <!-- <CompilerGeneratedFilesOutputPath>$(OutputPath)/$(TargetFramework)/Generated</CompilerGeneratedFilesOutputPath> -->
+ <EnableDefaultItems>true</EnableDefaultItems>
+ <!-- <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> -->
+ <DefineConstants>$(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER;ROSLYN_4_0_OR_GREATER</DefineConstants>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="$(CommonPath)..\tests\SourceGenerators\RoslynTestUtils.cs" Link="SourceGenerators\RoslynTestUtils.cs" />
+ <Compile Include="$(LibrariesProjectRoot)Microsoft.Extensions.Options\gen\DiagDescriptorsBase.cs" Link="gen\DiagDescriptorsBase.cs" />
+ <Compile Include="$(LibrariesProjectRoot)Microsoft.Extensions.Options\gen\DiagDescriptors.cs" Link="gen\DiagDescriptors.cs" />
+ </ItemGroup>
+
+ <ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETFramework'">
+ <ProjectReference Include="$(LibrariesProjectRoot)System.ComponentModel.Annotations\src\System.ComponentModel.Annotations.csproj" SkipUseReferenceAssembly="true" />
+ </ItemGroup>
+
+ <ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
+ <Reference Include="System.ComponentModel.DataAnnotations" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.CodeAnalysis" Version="$(MicrosoftCodeAnalysisVersion)" />
+ <ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Options\src\Microsoft.Extensions.Options.csproj" SkipUseReferenceAssembly="true" />
+ <ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Options\gen\Microsoft.Extensions.Options.SourceGeneration.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="true" />
+ </ItemGroup>
+
+ <Target Name="FixIncrementalCoreCompileWithAnalyzers" BeforeTargets="CoreCompile">
+ <ItemGroup>
+ <CustomAdditionalCompileInputs Include="@(Analyzer)" />
+ </ItemGroup>
+ </Target>
+</Project>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="ErrorMessageResourceName" xml:space="preserve">
+ <value>ErrorMessageResourceName</value>
+ </data>
+ <data name="CantUseWithGenericTypesTitle" xml:space="preserve">
+ <value>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</value>
+ </data>
+ <data name="PotentiallyMissingEnumerableValidationMessage" xml:space="preserve">
+ <value>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</value>
+ </data>
+ <data name="PotentiallyMissingEnumerableValidationTitle" xml:space="preserve">
+ <value>Member potentially missing enumerable validation.</value>
+ </data>
+ <data name="PotentiallyMissingTransitiveValidationMessage" xml:space="preserve">
+ <value>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</value>
+ </data>
+ <data name="CircularTypeReferencesMessage" xml:space="preserve">
+ <value>There is a circular type reference involving type {0} preventing it from being used for static validation.</value>
+ </data>
+ <data name="CircularTypeReferencesTitle" xml:space="preserve">
+ <value>Unsupported circular references in model types.</value>
+ </data>
+ <data name="MemberIsInaccessibleMessage" xml:space="preserve">
+ <value>Can't apply validation attributes to private field or property {0}.</value>
+ </data>
+ <data name="NotEnumerableTypeMessage" xml:space="preserve">
+ <value>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</value>
+ </data>
+ <data name="NullValidatorTypeTitle" xml:space="preserve">
+ <value>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</value>
+ </data>
+ <data name="CantUseWithGenericTypesMessage" xml:space="preserve">
+ <value>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</value>
+ </data>
+ <data name="NoEligibleMemberTitle" xml:space="preserve">
+ <value>A member type has no fields or properties to validate.</value>
+ </data>
+ <data name="NoEligibleMembersFromValidatorTitle" xml:space="preserve">
+ <value>A type has no fields or properties to validate.</value>
+ </data>
+ <data name="NotEnumerableTypeTitle" xml:space="preserve">
+ <value>Member type is not enumerable.</value>
+ </data>
+ <data name="ValidatorsNeedSimpleConstructorMessage" xml:space="preserve">
+ <value>Validator type {0} doesn't have a parameterless constructor.</value>
+ </data>
+ <data name="DoesntImplementIValidateOptionsMessage" xml:space="preserve">
+ <value>Type {0} does not implement the required IValidateOptions<{1}> interface.</value>
+ </data>
+ <data name="ValidatorsNeedSimpleConstructorTitle" xml:space="preserve">
+ <value>Validators used for transitive or enumerable validation must have a constructor with no parameters.</value>
+ </data>
+ <data name="NoEligibleMembersFromValidatorMessage" xml:space="preserve">
+ <value>Type {0} has no fields or properties to validate, referenced by type {1}.</value>
+ </data>
+ <data name="NoEligibleMemberMessage" xml:space="preserve">
+ <value>Type {0} has no fields or properties to validate, referenced from member {1}.</value>
+ </data>
+ <data name="DoesntImplementIValidateOptionsTitle" xml:space="preserve">
+ <value>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</value>
+ </data>
+ <data name="MemberIsInaccessibleTitle" xml:space="preserve">
+ <value>Can't validate private fields or properties.</value>
+ </data>
+ <data name="CantBeStaticClassMessage" xml:space="preserve">
+ <value>[OptionsValidator] cannot be applied to static class {0}.</value>
+ </data>
+ <data name="AlreadyImplementsValidateMethodTitle" xml:space="preserve">
+ <value>A type already includes an implementation of the 'Validate' method.</value>
+ </data>
+ <data name="AlreadyImplementsValidateMethodMessage" xml:space="preserve">
+ <value>Type {0} already implements the Validate method.</value>
+ </data>
+ <data name="CantBeStaticClassTitle" xml:space="preserve">
+ <value>'OptionsValidatorAttribute' can't be applied to a static class.</value>
+ </data>
+ <data name="NullValidatorTypeMessage" xml:space="preserve">
+ <value>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</value>
+ </data>
+ <data name="PotentiallyMissingTransitiveValidationTitle" xml:space="preserve">
+ <value>Member potentially missing transitive validation.</value>
+ </data>
+</root>
\ No newline at end of file
--- /dev/null
+
+ // <auto-generated/>
+ #nullable enable
+ #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+internal sealed partial class __ThirdModelNoNamespaceValidator__
+{
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ThirdModelNoNamespace options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModelNoNamespace" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+}
+partial class FirstValidatorNoNamespace
+{
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FirstModelNoNamespace options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModelNoNamespace" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V1.Validate(baseName + "P2", options.P2));
+ }
+
+ if (options.P3 is not null)
+ {
+ builder.AddResult(global::__ThirdModelNoNamespaceValidator__.Validate(baseName + "P3", options.P3));
+ }
+
+ return builder.Build();
+ }
+}
+partial class SecondValidatorNoNamespace
+{
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SecondModelNoNamespace options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModelNoNamespace" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P4";
+ context.DisplayName = baseName + "P4";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+}
+namespace CustomAttr
+{
+ partial class FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::CustomAttr.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A3);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "P2";
+ context.DisplayName = baseName + "P2";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A4);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P2!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Enumeration
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __SecondModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P6";
+ context.DisplayName = baseName + "P6";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Enumeration
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __ThirdModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.ThirdModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Value";
+ context.DisplayName = baseName + "Value";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A5);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Value!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Enumeration
+{
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options);
+
+ if (options.P1 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P1)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P1[{count}]", o));
+ }
+ else
+ {
+ builder.AddError(baseName + $"P1[{count}] is null");
+ }
+ count++;
+ }
+ }
+
+ if (options.P2 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P2)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V2.Validate(baseName + $"P2[{count}]", o));
+ }
+ else
+ {
+ builder.AddError(baseName + $"P2[{count}] is null");
+ }
+ count++;
+ }
+ }
+
+ if (options.P3 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P3)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P3[{count}]", o));
+ }
+ count++;
+ }
+ }
+
+ if (options.P4 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P4)
+ {
+ builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P4[{count++}]", o));
+ }
+ }
+
+ if (options.P5 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P5)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P5[{count}]", o.Value));
+ }
+ count++;
+ }
+ }
+
+ if (options.P51 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P51)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P51[{count}]", o.Value));
+ }
+ count++;
+ }
+ }
+
+ if (options.P6 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P6.Value)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P6[{count}]", o));
+ }
+ else
+ {
+ builder.AddError(baseName + $"P6[{count}] is null");
+ }
+ count++;
+ }
+ }
+
+ {
+ var count = 0;
+ foreach (var o in options.P7)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P7[{count}]", o));
+ }
+ else
+ {
+ builder.AddError(baseName + $"P7[{count}] is null");
+ }
+ count++;
+ }
+ }
+
+ if (options.P8 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P8.Value)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P8[{count}]", o));
+ }
+ else
+ {
+ builder.AddError(baseName + $"P8[{count}] is null");
+ }
+ count++;
+ }
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Enumeration
+{
+ partial struct SecondValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P6";
+ context.DisplayName = baseName + "P6";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Fields
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __ThirdModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Fields.ThirdModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Fields
+{
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Fields.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V3.Validate(baseName + "P2", options.P2));
+ }
+
+ builder.AddResult(global::Fields.__ThirdModelValidator__.Validate(baseName + "P3", options.P3));
+
+ return builder.Build();
+ }
+ }
+}
+namespace Fields
+{
+ partial struct SecondValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Fields.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P4";
+ context.DisplayName = baseName + "P4";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace FileScopedNamespace
+{
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FileScopedNamespace.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace FunnyStrings
+{
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FunnyStrings.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A6);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Generics
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __SecondModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Generics.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P4";
+ context.DisplayName = baseName + "P4";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Generics
+{
+ partial class FirstValidator<T>
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Generics.FirstModel<T> options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P3 is not null)
+ {
+ builder.AddResult(global::Generics.__SecondModelValidator__.Validate(baseName + "P3", options.P3));
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace MultiModelValidator
+{
+ partial struct MultiValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::MultiModelValidator.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V4.Validate(baseName + "P2", options.P2));
+ }
+
+ return builder.Build();
+ }
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::MultiModelValidator.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P3";
+ context.DisplayName = baseName + "P3";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P3!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Nested
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __ThirdModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.ThirdModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P6";
+ context.DisplayName = baseName + "P6";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Nested
+{
+ partial record struct Container7
+ {
+ partial record struct FifthValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+ }
+}
+namespace Nested
+{
+ partial class Container2
+ {
+ partial class Container3
+ {
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V5.Validate(baseName + "P2", options.P2));
+ }
+
+ builder.AddResult(global::Nested.__ThirdModelValidator__.Validate(baseName + "P3", options.P3));
+
+ if (options.P4 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V6.Validate(baseName + "P4", options.P4));
+ }
+
+ return builder.Build();
+ }
+ }
+ }
+ }
+}
+namespace Nested
+{
+ partial struct Container6
+ {
+ partial struct FourthValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+ }
+}
+namespace Nested
+{
+ partial class Container2
+ {
+ partial class Container3
+ {
+ partial struct SecondValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+ }
+ }
+}
+namespace Nested
+{
+ partial record class Container4
+ {
+ partial record class Container5
+ {
+ partial struct ThirdValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+ }
+ }
+}
+namespace RandomMembers
+{
+ partial class FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RandomMembers.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace RecordTypes
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __ThirdModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.ThirdModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P6";
+ context.DisplayName = baseName + "P6";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace RecordTypes
+{
+ partial record struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V7.Validate(baseName + "P2", options.P2));
+ }
+
+ if (options.P3 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V8.Validate(baseName + "P3", options.P3));
+ }
+
+ builder.AddResult(global::RecordTypes.__ThirdModelValidator__.Validate(baseName + "P4", options.P4));
+
+ return builder.Build();
+ }
+ }
+}
+namespace RecordTypes
+{
+ partial record struct SecondValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace RecordTypes
+{
+ partial record class ThirdValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace RepeatedTypes
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __SecondModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "P4";
+ context.DisplayName = baseName + "P4";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P4 is not null)
+ {
+ builder.AddResult(global::RepeatedTypes.__ThirdModelValidator__.Validate(baseName + "P4", options.P4));
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace RepeatedTypes
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __ThirdModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.ThirdModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace RepeatedTypes
+{
+ partial class FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P1 is not null)
+ {
+ builder.AddResult(global::RepeatedTypes.__SecondModelValidator__.Validate(baseName + "P1", options.P1));
+ }
+
+ context.MemberName = "P2";
+ context.DisplayName = baseName + "P2";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P2!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::RepeatedTypes.__SecondModelValidator__.Validate(baseName + "P2", options.P2));
+ }
+
+ context.MemberName = "P3";
+ context.DisplayName = baseName + "P3";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P3!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P3 is not null)
+ {
+ builder.AddResult(global::RepeatedTypes.__ThirdModelValidator__.Validate(baseName + "P3", options.P3));
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace SelfValidation
+{
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SelfValidation.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ builder.AddResults(((global::System.ComponentModel.DataAnnotations.IValidatableObject)options).Validate(context));
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __RangeAttributeModelDoubleValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDouble options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A7);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __RequiredAttributeModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RequiredAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RequiredAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __TypeWithoutOptionsValidatorValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.TypeWithoutOptionsValidator options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "TypeWithoutOptionsValidator" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val1";
+ context.DisplayName = baseName + "Val1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val2";
+ context.DisplayName = baseName + "Val2";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A8);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.YetAnotherComplexVal is not null)
+ {
+ builder.AddResult(global::TestClasses.OptionsValidation.__RangeAttributeModelDoubleValidator__.Validate(baseName + "YetAnotherComplexVal", options.YetAnotherComplexVal));
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class AttributePropertyModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.AttributePropertyModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "AttributePropertyModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val1";
+ context.DisplayName = baseName + "Val1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A9);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val2";
+ context.DisplayName = baseName + "Val2";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A10);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class ComplexModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.ComplexModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ComplexModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options);
+
+ if (options.ComplexVal is not null)
+ {
+ builder.AddResult(global::TestClasses.OptionsValidation.__RequiredAttributeModelValidator__.Validate(baseName + "ComplexVal", options.ComplexVal));
+ }
+
+ if (options.ValWithoutOptionsValidator is not null)
+ {
+ builder.AddResult(global::TestClasses.OptionsValidation.__TypeWithoutOptionsValidatorValidator__.Validate(baseName + "ValWithoutOptionsValidator", options.ValWithoutOptionsValidator));
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class CustomTypeCustomValidationAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.CustomTypeCustomValidationAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "CustomTypeCustomValidationAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A11);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class CustomValidationAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.CustomValidationAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "CustomValidationAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A12);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class DataTypeAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.DataTypeAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "DataTypeAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A13);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class DerivedModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.DerivedModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "DerivedModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "DerivedVal";
+ context.DisplayName = baseName + "DerivedVal";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.DerivedVal!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "VirtualValWithAttr";
+ context.DisplayName = baseName + "VirtualValWithAttr";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.VirtualValWithAttr!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class EmailAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.EmailAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "EmailAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A14);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class LeafModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.LeafModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "LeafModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "VirtualValWithoutAttr";
+ context.DisplayName = baseName + "VirtualValWithoutAttr";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.VirtualValWithoutAttr!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "DerivedVal";
+ context.DisplayName = baseName + "DerivedVal";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.DerivedVal!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class MultipleAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.MultipleAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "MultipleAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "Val1";
+ context.DisplayName = baseName + "Val1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A15);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val2";
+ context.DisplayName = baseName + "Val2";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A16);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val3";
+ context.DisplayName = baseName + "Val3";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A17);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val3!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val4";
+ context.DisplayName = baseName + "Val4";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A18);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val4!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class RangeAttributeModelDateValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDate options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDate" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A19);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class RangeAttributeModelDoubleValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDouble options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A7);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class RangeAttributeModelIntValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelInt options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelInt" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A16);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class RegularExpressionAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RegularExpressionAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RegularExpressionAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A20);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class RequiredAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RequiredAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RequiredAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace ValueTypes
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __SecondModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValueTypes.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P4";
+ context.DisplayName = baseName + "P4";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace ValueTypes
+{
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValueTypes.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P2", options.P2.Value));
+ }
+
+ builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P3", options.P3));
+
+ if (options.P4 is not null)
+ {
+ builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P4", options.P4.Value));
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace __OptionValidationStaticInstances
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal static class __Attributes
+ {
+ internal static readonly global::System.ComponentModel.DataAnnotations.RequiredAttribute A1 = new global::System.ComponentModel.DataAnnotations.RequiredAttribute();
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.MinLengthAttribute A2 = new global::System.ComponentModel.DataAnnotations.MinLengthAttribute(
+ (int)5);
+
+ internal static readonly global::CustomAttr.CustomAttribute A3 = new global::CustomAttr.CustomAttribute(
+ 'A',
+ true,
+ null);
+
+ internal static readonly global::CustomAttr.CustomAttribute A4 = new global::CustomAttr.CustomAttribute(
+ 'A',
+ false,
+ "X");
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A5 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)0,
+ (int)10);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute A6 = new global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute(
+ "\"\r\n\\\\");
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A7 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (double)0.5,
+ (double)0.9);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A8 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ typeof(global::System.DateTime),
+ "1/2/2004",
+ "3/4/2004");
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A9 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)1,
+ (int)3)
+ {
+ ErrorMessage = "ErrorMessage"
+ };
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A10 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)1,
+ (int)3)
+ {
+ ErrorMessageResourceName = "ErrorMessageResourceName",
+ ErrorMessageResourceType = typeof(global::System.SR)
+ };
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.CustomValidationAttribute A11 = new global::System.ComponentModel.DataAnnotations.CustomValidationAttribute(
+ typeof(global::TestClasses.OptionsValidation.CustomTypeCustomValidationTest),
+ "TestMethod");
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.CustomValidationAttribute A12 = new global::System.ComponentModel.DataAnnotations.CustomValidationAttribute(
+ typeof(global::TestClasses.OptionsValidation.CustomValidationTest),
+ "TestMethod");
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.DataTypeAttribute A13 = new global::System.ComponentModel.DataAnnotations.DataTypeAttribute(
+ (global::System.ComponentModel.DataAnnotations.DataType)7);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.EmailAddressAttribute A14 = new global::System.ComponentModel.DataAnnotations.EmailAddressAttribute();
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.DataTypeAttribute A15 = new global::System.ComponentModel.DataAnnotations.DataTypeAttribute(
+ (global::System.ComponentModel.DataAnnotations.DataType)11);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A16 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)1,
+ (int)3);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A17 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)3,
+ (int)5);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A18 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)5,
+ (int)9);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A19 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ typeof(global::System.DateTime),
+ "1/2/2004",
+ "3/4/2004")
+ {
+ ParseLimitsInInvariantCulture = true
+ };
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute A20 = new global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute(
+ "\\s");
+ }
+}
+namespace __OptionValidationStaticInstances
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal static class __Validators
+ {
+ internal static readonly global::SecondValidatorNoNamespace V1 = new global::SecondValidatorNoNamespace();
+
+ internal static readonly global::Enumeration.SecondValidator V2 = new global::Enumeration.SecondValidator();
+
+ internal static readonly global::Fields.SecondValidator V3 = new global::Fields.SecondValidator();
+
+ internal static readonly global::MultiModelValidator.MultiValidator V4 = new global::MultiModelValidator.MultiValidator();
+
+ internal static readonly global::Nested.Container2.Container3.SecondValidator V5 = new global::Nested.Container2.Container3.SecondValidator();
+
+ internal static readonly global::Nested.Container4.Container5.ThirdValidator V6 = new global::Nested.Container4.Container5.ThirdValidator();
+
+ internal static readonly global::RecordTypes.SecondValidator V7 = new global::RecordTypes.SecondValidator();
+
+ internal static readonly global::RecordTypes.ThirdValidator V8 = new global::RecordTypes.ThirdValidator();
+ }
+}
--- /dev/null
+
+ // <auto-generated/>
+ #nullable enable
+ #pragma warning disable CS1591 // Compensate for https://github.com/dotnet/roslyn/issues/54103
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+internal sealed partial class __ThirdModelNoNamespaceValidator__
+{
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ThirdModelNoNamespace options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModelNoNamespace" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+}
+partial class FirstValidatorNoNamespace
+{
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FirstModelNoNamespace options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModelNoNamespace" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V1.Validate(baseName + "P2", options.P2));
+ }
+
+ if (options.P3 is not null)
+ {
+ builder.AddResult(global::__ThirdModelNoNamespaceValidator__.Validate(baseName + "P3", options.P3));
+ }
+
+ return builder.Build();
+ }
+}
+partial class SecondValidatorNoNamespace
+{
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SecondModelNoNamespace options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModelNoNamespace" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P4";
+ context.DisplayName = baseName + "P4";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+}
+namespace CustomAttr
+{
+ partial class FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::CustomAttr.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A3);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "P2";
+ context.DisplayName = baseName + "P2";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A4);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P2!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Enumeration
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __SecondModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P6";
+ context.DisplayName = baseName + "P6";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Enumeration
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __ThirdModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.ThirdModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Value";
+ context.DisplayName = baseName + "Value";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A5);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Value!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Enumeration
+{
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options);
+
+ if (options.P1 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P1)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P1[{count}]", o));
+ }
+ else
+ {
+ builder.AddError(baseName + $"P1[{count}] is null");
+ }
+ count++;
+ }
+ }
+
+ if (options.P2 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P2)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V2.Validate(baseName + $"P2[{count}]", o));
+ }
+ else
+ {
+ builder.AddError(baseName + $"P2[{count}] is null");
+ }
+ count++;
+ }
+ }
+
+ if (options.P3 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P3)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P3[{count}]", o));
+ }
+ count++;
+ }
+ }
+
+ if (options.P4 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P4)
+ {
+ builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P4[{count++}]", o));
+ }
+ }
+
+ if (options.P5 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P5)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P5[{count}]", o.Value));
+ }
+ count++;
+ }
+ }
+
+ if (options.P51 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P51)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__ThirdModelValidator__.Validate(baseName + $"P51[{count}]", o.Value));
+ }
+ count++;
+ }
+ }
+
+ if (options.P6 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P6.Value)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P6[{count}]", o));
+ }
+ else
+ {
+ builder.AddError(baseName + $"P6[{count}] is null");
+ }
+ count++;
+ }
+ }
+
+ {
+ var count = 0;
+ foreach (var o in options.P7)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P7[{count}]", o));
+ }
+ else
+ {
+ builder.AddError(baseName + $"P7[{count}] is null");
+ }
+ count++;
+ }
+ }
+
+ if (options.P8 is not null)
+ {
+ var count = 0;
+ foreach (var o in options.P8.Value)
+ {
+ if (o is not null)
+ {
+ builder.AddResult(global::Enumeration.__SecondModelValidator__.Validate(baseName + $"P8[{count}]", o));
+ }
+ else
+ {
+ builder.AddError(baseName + $"P8[{count}] is null");
+ }
+ count++;
+ }
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Enumeration
+{
+ partial struct SecondValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Enumeration.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P6";
+ context.DisplayName = baseName + "P6";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Fields
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __ThirdModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Fields.ThirdModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Fields
+{
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Fields.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V3.Validate(baseName + "P2", options.P2));
+ }
+
+ builder.AddResult(global::Fields.__ThirdModelValidator__.Validate(baseName + "P3", options.P3));
+
+ return builder.Build();
+ }
+ }
+}
+namespace Fields
+{
+ partial struct SecondValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Fields.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P4";
+ context.DisplayName = baseName + "P4";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace FileScopedNamespace
+{
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FileScopedNamespace.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace FunnyStrings
+{
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::FunnyStrings.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A6);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Generics
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __SecondModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Generics.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P4";
+ context.DisplayName = baseName + "P4";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Generics
+{
+ partial class FirstValidator<T>
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Generics.FirstModel<T> options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P3 is not null)
+ {
+ builder.AddResult(global::Generics.__SecondModelValidator__.Validate(baseName + "P3", options.P3));
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace MultiModelValidator
+{
+ partial struct MultiValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::MultiModelValidator.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V4.Validate(baseName + "P2", options.P2));
+ }
+
+ return builder.Build();
+ }
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::MultiModelValidator.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P3";
+ context.DisplayName = baseName + "P3";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P3!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Nested
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __ThirdModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.ThirdModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P6";
+ context.DisplayName = baseName + "P6";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace Nested
+{
+ partial record struct Container7
+ {
+ partial record struct FifthValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+ }
+}
+namespace Nested
+{
+ partial class Container2
+ {
+ partial class Container3
+ {
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V5.Validate(baseName + "P2", options.P2));
+ }
+
+ builder.AddResult(global::Nested.__ThirdModelValidator__.Validate(baseName + "P3", options.P3));
+
+ if (options.P4 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V6.Validate(baseName + "P4", options.P4));
+ }
+
+ return builder.Build();
+ }
+ }
+ }
+ }
+}
+namespace Nested
+{
+ partial struct Container6
+ {
+ partial struct FourthValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+ }
+}
+namespace Nested
+{
+ partial class Container2
+ {
+ partial class Container3
+ {
+ partial struct SecondValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+ }
+ }
+}
+namespace Nested
+{
+ partial record class Container4
+ {
+ partial record class Container5
+ {
+ partial struct ThirdValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::Nested.Container1.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+ }
+ }
+}
+namespace RandomMembers
+{
+ partial class FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RandomMembers.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace RecordTypes
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __ThirdModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.ThirdModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P6";
+ context.DisplayName = baseName + "P6";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P6!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace RecordTypes
+{
+ partial record struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V7.Validate(baseName + "P2", options.P2));
+ }
+
+ if (options.P3 is not null)
+ {
+ builder.AddResult(global::__OptionValidationStaticInstances.__Validators.V8.Validate(baseName + "P3", options.P3));
+ }
+
+ builder.AddResult(global::RecordTypes.__ThirdModelValidator__.Validate(baseName + "P4", options.P4));
+
+ return builder.Build();
+ }
+ }
+}
+namespace RecordTypes
+{
+ partial record struct SecondValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace RecordTypes
+{
+ partial record class ThirdValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RecordTypes.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace RepeatedTypes
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __SecondModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "P4";
+ context.DisplayName = baseName + "P4";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P4 is not null)
+ {
+ builder.AddResult(global::RepeatedTypes.__ThirdModelValidator__.Validate(baseName + "P4", options.P4));
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace RepeatedTypes
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __ThirdModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.ThirdModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ThirdModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P5";
+ context.DisplayName = baseName + "P5";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P5!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace RepeatedTypes
+{
+ partial class FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::RepeatedTypes.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P1 is not null)
+ {
+ builder.AddResult(global::RepeatedTypes.__SecondModelValidator__.Validate(baseName + "P1", options.P1));
+ }
+
+ context.MemberName = "P2";
+ context.DisplayName = baseName + "P2";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P2!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::RepeatedTypes.__SecondModelValidator__.Validate(baseName + "P2", options.P2));
+ }
+
+ context.MemberName = "P3";
+ context.DisplayName = baseName + "P3";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P3!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P3 is not null)
+ {
+ builder.AddResult(global::RepeatedTypes.__ThirdModelValidator__.Validate(baseName + "P3", options.P3));
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace SelfValidation
+{
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::SelfValidation.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ builder.AddResults(((global::System.ComponentModel.DataAnnotations.IValidatableObject)options).Validate(context));
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __RangeAttributeModelDoubleValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDouble options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A7);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __RequiredAttributeModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RequiredAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RequiredAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __TypeWithoutOptionsValidatorValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.TypeWithoutOptionsValidator options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "TypeWithoutOptionsValidator" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val1";
+ context.DisplayName = baseName + "Val1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val2";
+ context.DisplayName = baseName + "Val2";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A8);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.YetAnotherComplexVal is not null)
+ {
+ builder.AddResult(global::TestClasses.OptionsValidation.__RangeAttributeModelDoubleValidator__.Validate(baseName + "YetAnotherComplexVal", options.YetAnotherComplexVal));
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class AttributePropertyModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.AttributePropertyModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "AttributePropertyModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val1";
+ context.DisplayName = baseName + "Val1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A9);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val2";
+ context.DisplayName = baseName + "Val2";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A10);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class ComplexModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.ComplexModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "ComplexModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ var context = new global::System.ComponentModel.DataAnnotations.ValidationContext(options);
+
+ if (options.ComplexVal is not null)
+ {
+ builder.AddResult(global::TestClasses.OptionsValidation.__RequiredAttributeModelValidator__.Validate(baseName + "ComplexVal", options.ComplexVal));
+ }
+
+ if (options.ValWithoutOptionsValidator is not null)
+ {
+ builder.AddResult(global::TestClasses.OptionsValidation.__TypeWithoutOptionsValidatorValidator__.Validate(baseName + "ValWithoutOptionsValidator", options.ValWithoutOptionsValidator));
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class CustomTypeCustomValidationAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.CustomTypeCustomValidationAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "CustomTypeCustomValidationAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A11);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class CustomValidationAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.CustomValidationAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "CustomValidationAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A12);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class DataTypeAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.DataTypeAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "DataTypeAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A13);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class DerivedModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.DerivedModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "DerivedModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "DerivedVal";
+ context.DisplayName = baseName + "DerivedVal";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.DerivedVal!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "VirtualValWithAttr";
+ context.DisplayName = baseName + "VirtualValWithAttr";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.VirtualValWithAttr!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class EmailAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.EmailAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "EmailAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A14);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class LeafModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.LeafModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "LeafModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "VirtualValWithoutAttr";
+ context.DisplayName = baseName + "VirtualValWithoutAttr";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.VirtualValWithoutAttr!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "DerivedVal";
+ context.DisplayName = baseName + "DerivedVal";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.DerivedVal!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class MultipleAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.MultipleAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "MultipleAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "Val1";
+ context.DisplayName = baseName + "Val1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A15);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val2";
+ context.DisplayName = baseName + "Val2";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A16);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val2!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val3";
+ context.DisplayName = baseName + "Val3";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A17);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val3!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ context.MemberName = "Val4";
+ context.DisplayName = baseName + "Val4";
+ validationResults.Clear();
+ validationAttributes.Clear();
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A18);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val4!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class RangeAttributeModelDateValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDate options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDate" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A8);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class RangeAttributeModelDoubleValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelDouble options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelDouble" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A7);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class RangeAttributeModelIntValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RangeAttributeModelInt options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RangeAttributeModelInt" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A16);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class RegularExpressionAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RegularExpressionAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RegularExpressionAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A19);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace TestClasses.OptionsValidation
+{
+ partial class RequiredAttributeModelValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::TestClasses.OptionsValidation.RequiredAttributeModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "RequiredAttributeModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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>(1);
+
+ context.MemberName = "Val";
+ context.DisplayName = baseName + "Val";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.Val!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace ValueTypes
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal sealed partial class __SecondModelValidator__
+ {
+ /// <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", "42.42.42.42")]
+ public static global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValueTypes.SecondModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "SecondModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P4";
+ context.DisplayName = baseName + "P4";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P4!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace ValueTypes
+{
+ partial struct FirstValidator
+ {
+ /// <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", "42.42.42.42")]
+ public global::Microsoft.Extensions.Options.ValidateOptionsResult Validate(string? name, global::ValueTypes.FirstModel options)
+ {
+ var baseName = (string.IsNullOrEmpty(name) ? "FirstModel" : name) + ".";
+ var builder = new global::Microsoft.Extensions.Options.ValidateOptionsResultBuilder();
+ 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 = "P1";
+ context.DisplayName = baseName + "P1";
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A1);
+ validationAttributes.Add(global::__OptionValidationStaticInstances.__Attributes.A2);
+ if (!global::System.ComponentModel.DataAnnotations.Validator.TryValidateValue(options.P1!, context, validationResults, validationAttributes))
+ {
+ builder.AddResults(validationResults);
+ }
+
+ if (options.P2 is not null)
+ {
+ builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P2", options.P2.Value));
+ }
+
+ builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P3", options.P3));
+
+ if (options.P4 is not null)
+ {
+ builder.AddResult(global::ValueTypes.__SecondModelValidator__.Validate(baseName + "P4", options.P4.Value));
+ }
+
+ return builder.Build();
+ }
+ }
+}
+namespace __OptionValidationStaticInstances
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal static class __Attributes
+ {
+ internal static readonly global::System.ComponentModel.DataAnnotations.RequiredAttribute A1 = new global::System.ComponentModel.DataAnnotations.RequiredAttribute();
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.MinLengthAttribute A2 = new global::System.ComponentModel.DataAnnotations.MinLengthAttribute(
+ (int)5);
+
+ internal static readonly global::CustomAttr.CustomAttribute A3 = new global::CustomAttr.CustomAttribute(
+ 'A',
+ true,
+ null);
+
+ internal static readonly global::CustomAttr.CustomAttribute A4 = new global::CustomAttr.CustomAttribute(
+ 'A',
+ false,
+ "X");
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A5 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)0,
+ (int)10);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute A6 = new global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute(
+ "\"\r\n\\\\");
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A7 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (double)0.5,
+ (double)0.9);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A8 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ typeof(global::System.DateTime),
+ "1/2/2004",
+ "3/4/2004");
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A9 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)1,
+ (int)3)
+ {
+ ErrorMessage = "ErrorMessage"
+ };
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A10 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)1,
+ (int)3)
+ {
+ ErrorMessageResourceName = "ErrorMessageResourceName",
+ ErrorMessageResourceType = typeof(global::System.SR)
+ };
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.CustomValidationAttribute A11 = new global::System.ComponentModel.DataAnnotations.CustomValidationAttribute(
+ typeof(global::TestClasses.OptionsValidation.CustomTypeCustomValidationTest),
+ "TestMethod");
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.CustomValidationAttribute A12 = new global::System.ComponentModel.DataAnnotations.CustomValidationAttribute(
+ typeof(global::TestClasses.OptionsValidation.CustomValidationTest),
+ "TestMethod");
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.DataTypeAttribute A13 = new global::System.ComponentModel.DataAnnotations.DataTypeAttribute(
+ (global::System.ComponentModel.DataAnnotations.DataType)7);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.EmailAddressAttribute A14 = new global::System.ComponentModel.DataAnnotations.EmailAddressAttribute();
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.DataTypeAttribute A15 = new global::System.ComponentModel.DataAnnotations.DataTypeAttribute(
+ (global::System.ComponentModel.DataAnnotations.DataType)11);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A16 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)1,
+ (int)3);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A17 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)3,
+ (int)5);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RangeAttribute A18 = new global::System.ComponentModel.DataAnnotations.RangeAttribute(
+ (int)5,
+ (int)9);
+
+ internal static readonly global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute A19 = new global::System.ComponentModel.DataAnnotations.RegularExpressionAttribute(
+ "\\s");
+ }
+}
+namespace __OptionValidationStaticInstances
+{
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Options.SourceGeneration", "42.42.42.42")]
+ internal static class __Validators
+ {
+ internal static readonly global::SecondValidatorNoNamespace V1 = new global::SecondValidatorNoNamespace();
+
+ internal static readonly global::Enumeration.SecondValidator V2 = new global::Enumeration.SecondValidator();
+
+ internal static readonly global::Fields.SecondValidator V3 = new global::Fields.SecondValidator();
+
+ internal static readonly global::MultiModelValidator.MultiValidator V4 = new global::MultiModelValidator.MultiValidator();
+
+ internal static readonly global::Nested.Container2.Container3.SecondValidator V5 = new global::Nested.Container2.Container3.SecondValidator();
+
+ internal static readonly global::Nested.Container4.Container5.ThirdValidator V6 = new global::Nested.Container4.Container5.ThirdValidator();
+
+ internal static readonly global::RecordTypes.SecondValidator V7 = new global::RecordTypes.SecondValidator();
+
+ internal static readonly global::RecordTypes.ThirdValidator V8 = new global::RecordTypes.ThirdValidator();
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.IO;
+using System.Reflection;
+using System.Threading.Tasks;
+using SourceGenerators.Tests;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Options.Generators;
+using Microsoft.Shared.Data.Validation;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class EmitterTests
+{
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public async Task TestEmitter()
+ {
+ var sources = new List<string>();
+#pragma warning disable RS1035 // To allow using the File IO APIs inside the analyzer test
+ foreach (var file in Directory.GetFiles("TestClasses"))
+ {
+#if NETCOREAPP3_1_OR_GREATER
+ sources.Add("#define NETCOREAPP3_1_OR_GREATER\n" + File.ReadAllText(file));
+#else
+ sources.Add(File.ReadAllText(file));
+#endif
+ }
+
+ var (d, r) = await RoslynTestUtils.RunGenerator(
+ new Generator(),
+ new[]
+ {
+ Assembly.GetAssembly(typeof(RequiredAttribute))!,
+ Assembly.GetAssembly(typeof(TimeSpanAttribute))!,
+ Assembly.GetAssembly(typeof(OptionsValidatorAttribute))!,
+ Assembly.GetAssembly(typeof(IValidateOptions<object>))!,
+ },
+ sources)
+ .ConfigureAwait(false);
+
+ Assert.Empty(d);
+ _ = Assert.Single(r);
+
+#if NETCOREAPP3_1_OR_GREATER
+ string baseline = File.ReadAllText(@"Baselines/NetCoreApp/Validators.g.cs");
+#else
+ string baseline = File.ReadAllText(@"Baselines/NetFX/Validators.g.cs");
+#endif
+
+ string result = r[0].SourceText.ToString();
+ Assert.Equal(baseline, result);
+#pragma warning restore RS1035
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+#pragma warning disable CA1716
+namespace Microsoft.Shared.Collections;
+#pragma warning restore CA1716
+
+#if !SHARED_PROJECT
+[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+#endif
+
+[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "Static field, lifetime matches the process")]
+internal sealed class EmptyReadOnlyList<T> : IReadOnlyList<T>, ICollection<T>
+{
+ public static readonly EmptyReadOnlyList<T> Instance = new();
+ private readonly Enumerator _enumerator = new();
+
+ public IEnumerator<T> GetEnumerator() => _enumerator;
+ IEnumerator IEnumerable.GetEnumerator() => _enumerator;
+ public int Count => 0;
+ public T this[int index] => throw new ArgumentOutOfRangeException(nameof(index));
+
+ void ICollection<T>.CopyTo(T[] array, int arrayIndex)
+ {
+ // nop
+ }
+
+ bool ICollection<T>.Contains(T item) => false;
+ bool ICollection<T>.IsReadOnly => true;
+ void ICollection<T>.Add(T item) => throw new NotSupportedException();
+ bool ICollection<T>.Remove(T item) => false;
+
+ void ICollection<T>.Clear()
+ {
+ // nop
+ }
+
+ internal sealed class Enumerator : IEnumerator<T>
+ {
+ public void Dispose()
+ {
+ // nop
+ }
+
+ public void Reset()
+ {
+ // nop
+ }
+
+ public bool MoveNext() => false;
+ public T Current => throw new InvalidOperationException();
+ object IEnumerator.Current => throw new InvalidOperationException();
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+#pragma warning disable CA1716
+namespace Microsoft.Shared.Collections;
+#pragma warning restore CA1716
+
+#if !SHARED_PROJECT
+[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+#endif
+
+internal sealed class EmptyReadOnlyDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>, IDictionary<TKey, TValue>
+ where TKey : notnull
+{
+ public static readonly EmptyReadOnlyDictionary<TKey, TValue> Instance = new();
+
+ public int Count => 0;
+ public TValue this[TKey key] => throw new KeyNotFoundException();
+ public bool ContainsKey(TKey key) => false;
+ public IEnumerable<TKey> Keys => EmptyReadOnlyList<TKey>.Instance;
+ public IEnumerable<TValue> Values => EmptyReadOnlyList<TValue>.Instance;
+
+ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => EmptyReadOnlyList<KeyValuePair<TKey, TValue>>.Instance.GetEnumerator();
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
+ ICollection<TKey> IDictionary<TKey, TValue>.Keys => Array.Empty<TKey>();
+ ICollection<TValue> IDictionary<TKey, TValue>.Values => Array.Empty<TValue>();
+ bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => true;
+ TValue IDictionary<TKey, TValue>.this[TKey key]
+ {
+ get => throw new KeyNotFoundException();
+ set => throw new NotSupportedException();
+ }
+
+ public bool TryGetValue(TKey key, out TValue value)
+ {
+#pragma warning disable CS8601 // The recommended implementation: https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2.trygetvalue
+ value = default;
+#pragma warning restore
+
+ return false;
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.Clear()
+ {
+ // nop
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+ {
+ // nop
+ }
+
+ void IDictionary<TKey, TValue>.Add(TKey key, TValue value) => throw new NotSupportedException();
+ bool IDictionary<TKey, TValue>.Remove(TKey key) => false;
+ void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) => throw new NotSupportedException();
+ bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) => false;
+ bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) => false;
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+// using Microsoft.Shared.Diagnostics;
+
+#pragma warning disable CA1716
+namespace Microsoft.Shared.Data.Validation;
+#pragma warning restore CA1716
+
+/// <summary>
+/// Provides boundary validation for <see cref="TimeSpan"/>.
+/// </summary>
+#if !SHARED_PROJECT
+[ExcludeFromCodeCoverage]
+#endif
+
+[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
+[SuppressMessage("Design", "CA1019:Define accessors for attribute arguments", Justification = "Indirectly we are.")]
+internal sealed class TimeSpanAttribute : ValidationAttribute
+{
+ /// <summary>
+ /// Gets the lower bound for time span.
+ /// </summary>
+ public TimeSpan Minimum => _minMs.HasValue ? TimeSpan.FromMilliseconds((double)_minMs) : TimeSpan.Parse(_min!, CultureInfo.InvariantCulture);
+
+ /// <summary>
+ /// Gets the upper bound for time span.
+ /// </summary>
+ public TimeSpan? Maximum
+ {
+ get
+ {
+ if (_maxMs.HasValue)
+ {
+ return TimeSpan.FromMilliseconds((double)_maxMs);
+ }
+ else
+ {
+ return _max == null ? null : TimeSpan.Parse(_max, CultureInfo.InvariantCulture);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the time span validation should exclude the minimum and maximum values.
+ /// </summary>
+ /// <remarks>
+ /// By default the property is set to <c>false</c>.
+ /// </remarks>
+ public bool Exclusive { get; set; }
+
+ private readonly int? _minMs;
+ private readonly int? _maxMs;
+ private readonly string? _min;
+ private readonly string? _max;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TimeSpanAttribute"/> class.
+ /// </summary>
+ /// <param name="minMs">Minimum in milliseconds.</param>
+ public TimeSpanAttribute(int minMs)
+ {
+ _minMs = minMs;
+ _maxMs = null;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TimeSpanAttribute"/> class.
+ /// </summary>
+ /// <param name="minMs">Minimum in milliseconds.</param>
+ /// <param name="maxMs">Maximum in milliseconds.</param>
+ public TimeSpanAttribute(int minMs, int maxMs)
+ {
+ _minMs = minMs;
+ _maxMs = maxMs;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TimeSpanAttribute"/> class.
+ /// </summary>
+ /// <param name="min">Minimum represented as time span string.</param>
+ public TimeSpanAttribute(string min)
+ {
+ _ = ThrowHelper.IfNullOrWhitespace(min);
+
+ _min = min;
+ _max = null;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TimeSpanAttribute"/> class.
+ /// </summary>
+ /// <param name="min">Minimum represented as time span string.</param>
+ /// <param name="max">Maximum represented as time span string.</param>
+ public TimeSpanAttribute(string min, string max)
+ {
+ _ = ThrowHelper.IfNullOrWhitespace(min);
+ _ = ThrowHelper.IfNullOrWhitespace(max);
+
+ _min = min;
+ _max = max;
+ }
+
+ /// <summary>
+ /// Validates that a given value represents an in-range TimeSpan value.
+ /// </summary>
+ /// <param name="value">The value to validate.</param>
+ /// <param name="validationContext">Additional context for this validation.</param>
+ /// <returns>A value indicating success or failure.</returns>
+ protected override ValidationResult IsValid(object? value, ValidationContext? validationContext)
+ {
+ var min = Minimum;
+ var max = Maximum;
+
+ if (min >= max)
+ {
+ throw new InvalidOperationException($"{nameof(TimeSpanAttribute)} requires that the minimum value be less than the maximum value (see field {validationContext.GetDisplayName()})");
+ }
+
+ if (value == null)
+ {
+ // use the [Required] attribute to force presence
+ return ValidationResult.Success!;
+ }
+
+ if (value is TimeSpan ts)
+ {
+ if (Exclusive && ts <= min)
+ {
+ return new ValidationResult($"The field {validationContext.GetDisplayName()} must be > to {min}.", validationContext.GetMemberName());
+ }
+
+ if (ts < min)
+ {
+ return new ValidationResult($"The field {validationContext.GetDisplayName()} must be >= to {min}.", validationContext.GetMemberName());
+ }
+
+ if (max.HasValue)
+ {
+ if (Exclusive && ts >= max.Value)
+ {
+ return new ValidationResult($"The field {validationContext.GetDisplayName()} must be < to {max}.", validationContext.GetMemberName());
+ }
+
+ if (ts > max.Value)
+ {
+ return new ValidationResult($"The field {validationContext.GetDisplayName()} must be <= to {max}.", validationContext.GetMemberName());
+ }
+ }
+
+ return ValidationResult.Success!;
+ }
+
+ throw new InvalidOperationException($"{nameof(TimeSpanAttribute)} can only be used with fields of type TimeSpan (see field {validationContext.GetDisplayName()})");
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.ComponentModel.DataAnnotations;
+
+#pragma warning disable CA1716
+namespace Microsoft.Shared.Data.Validation;
+#pragma warning restore CA1716
+
+#if !SHARED_PROJECT
+[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+#endif
+
+internal static class ValidationContextExtensions
+{
+ public static string[]? GetMemberName(this ValidationContext? validationContext)
+ {
+#pragma warning disable S1168 // Empty arrays and collections should be returned instead of null
+ return validationContext?.MemberName is { } memberName
+ ? new[] { memberName }
+ : null;
+#pragma warning restore S1168 // Empty arrays and collections should be returned instead of null
+ }
+
+ public static string GetDisplayName(this ValidationContext? validationContext)
+ {
+ return validationContext?.DisplayName ?? string.Empty;
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using CustomAttr;
+using Microsoft.Extensions.Options;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class CustomAttrTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var firstModel = new FirstModel
+ {
+ P1 = 'a',
+ P2 = 'x',
+ };
+
+ var validator = new FirstValidator();
+ var vr = validator.Validate("CustomAttr", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 2, "P1", "P2");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var firstModel = new FirstModel
+ {
+ P1 = 'A',
+ P2 = 'A',
+ };
+
+ var validator = new FirstValidator();
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("CustomAttr", firstModel));
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Enumeration;
+using Microsoft.Extensions.Options;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class EnumerationTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var secondModelC = new SecondModel
+ {
+ P6 = "1234",
+ };
+
+ var secondModelB = new SecondModel
+ {
+ P6 = "12345",
+ };
+
+ var secondModel = new SecondModel
+ {
+ P6 = "1234",
+ };
+
+ ThirdModel? thirdModel = new ThirdModel
+ {
+ Value = 11
+ };
+
+ var firstModel = new FirstModel
+ {
+ P1 = new[] { secondModel },
+ P2 = new[] { secondModel, secondModelB, secondModelC },
+ P51 = new[] { thirdModel }
+ };
+
+ var validator = default(FirstValidator);
+ var vr = validator.Validate("Enumeration", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 4, "P1[0].P6", "P2[0].P6", "P2[2].P6", "P51[0].Value");
+ }
+
+ [Fact]
+ public void NullElement()
+ {
+ var firstModel = new FirstModel
+ {
+ P1 = new[] { (SecondModel)null! },
+ };
+
+ var validator = default(FirstValidator);
+ var vr = validator.Validate("Enumeration", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 1, "P1[0]");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var secondModel = new SecondModel
+ {
+ P6 = "12345",
+ };
+
+ var thirdModelA = new ThirdModel
+ {
+ Value = 2
+ };
+
+ var thirdModelB = new ThirdModel
+ {
+ Value = 9
+ };
+
+ var firstModel = new FirstModel
+ {
+ P1 = new[] { secondModel },
+ P2 = new[] { secondModel },
+ P3 = new[] { (SecondModel?)null },
+ P4 = new[] { thirdModelA, thirdModelB },
+ P5 = new ThirdModel?[] { thirdModelA, default },
+ P51 = new ThirdModel?[] { thirdModelB, default }
+ };
+
+ var validator = default(FirstValidator);
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("Enumeration", firstModel));
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Fields;
+using Microsoft.Extensions.Options;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class FieldTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var thirdModel = new ThirdModel
+ {
+ P5 = "1234",
+ };
+
+ var secondModel = new SecondModel
+ {
+ P4 = "1234",
+ };
+
+ var firstModel = new FirstModel
+ {
+ P1 = "1234",
+ P2 = secondModel,
+ P3 = thirdModel,
+ };
+
+ var validator = default(FirstValidator);
+ var vr = validator.Validate("Fields", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 3, "P1", "P2.P4", "P3.P5");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var thirdModel = new ThirdModel
+ {
+ P5 = "12345",
+ P6 = 1
+ };
+
+ var secondModel = new SecondModel
+ {
+ P4 = "12345",
+ };
+
+ var firstModel = new FirstModel
+ {
+ P1 = "12345",
+ P2 = secondModel,
+ P3 = thirdModel,
+ };
+
+ var validator = default(FirstValidator);
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("Fields", firstModel));
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using FunnyStrings;
+using Microsoft.Extensions.Options;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class FunnyStringsTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var firstModel = new FirstModel
+ {
+ P1 = "XXX",
+ };
+
+ var validator = default(FirstValidator);
+ var vr = validator.Validate("FunnyStrings", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 1, "P1");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var firstModel = new FirstModel
+ {
+ P1 = "\"\r\n\\",
+ };
+
+ var validator = default(FirstValidator);
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("FunnyStrings", firstModel));
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Generics;
+using Microsoft.Extensions.Options;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class GenericsTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var secondModel = new SecondModel
+ {
+ P4 = "1234",
+ };
+
+ var firstModel = new FirstModel<int>
+ {
+ P1 = "1234",
+ P3 = secondModel,
+ };
+
+ var validator = new FirstValidator<int>();
+ var vr = validator.Validate("Generics", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 2, "P1", "P3.P4");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var secondModel = new SecondModel
+ {
+ P4 = "12345",
+ };
+
+ var firstModel = new FirstModel<int>
+ {
+ P1 = "12345",
+ P3 = secondModel,
+ };
+
+ var validator = new FirstValidator<int>();
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("Generics", firstModel));
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Options;
+using MultiModelValidator;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class MultiModelValidatorTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var secondModel = new SecondModel
+ {
+ P3 = "1234",
+ };
+
+ var firstModel = new FirstModel
+ {
+ P1 = "1234",
+ P2 = secondModel,
+ };
+
+ var validator = default(MultiValidator);
+ var vr = validator.Validate("MultiModelValidator", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 2, "P1", "P2.P3");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var secondModel = new SecondModel
+ {
+ P3 = "12345",
+ };
+
+ var firstModel = new FirstModel
+ {
+ P1 = "12345",
+ P2 = secondModel,
+ };
+
+ var validator = default(MultiValidator);
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("MultiModelValidator", firstModel));
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#if ROSLYN_4_0_OR_GREATER
+
+using Microsoft.Extensions.Options;
+using Nested;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class NestedTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var thirdModel = new Container1.ThirdModel
+ {
+ P6 = "1234",
+ };
+
+ var secondModel = new Container1.SecondModel
+ {
+ P5 = "1234",
+ };
+
+ var firstModel = new Container1.FirstModel
+ {
+ P1 = "1234",
+ P2 = secondModel,
+ P3 = thirdModel,
+ P4 = secondModel,
+ };
+
+ var validator = default(Container2.Container3.FirstValidator);
+ var vr = validator.Validate("Nested", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 4, "P1", "P2.P5", "P3.P6", "P4.P5");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var thirdModel = new Container1.ThirdModel
+ {
+ P6 = "12345",
+ };
+
+ var secondModel = new Container1.SecondModel
+ {
+ P5 = "12345",
+ };
+
+ var firstModel = new Container1.FirstModel
+ {
+ P1 = "12345",
+ P2 = secondModel,
+ P3 = thirdModel,
+ P4 = secondModel,
+ };
+
+ var validator = default(Container2.Container3.FirstValidator);
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("Nested", firstModel));
+ }
+}
+
+#endif
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Options;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class NoNamespaceTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var thirdModel = new ThirdModelNoNamespace
+ {
+ P5 = "1234",
+ };
+
+ var secondModel = new SecondModelNoNamespace
+ {
+ P4 = "1234",
+ };
+
+ var firstModel = new FirstModelNoNamespace
+ {
+ P1 = "1234",
+ P2 = secondModel,
+ P3 = thirdModel,
+ };
+
+ var validator = new FirstValidatorNoNamespace();
+ var vr = validator.Validate("NoNamespace", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 3, "P1", "P2.P4", "P3.P5");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var thirdModel = new ThirdModelNoNamespace
+ {
+ P5 = "12345",
+ };
+
+ var secondModel = new SecondModelNoNamespace
+ {
+ P4 = "12345",
+ };
+
+ var firstModel = new FirstModelNoNamespace
+ {
+ P1 = "12345",
+ P2 = secondModel,
+ P3 = thirdModel,
+ };
+
+ var validator = new FirstValidatorNoNamespace();
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("NoNamespace", firstModel));
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Globalization;
+using Microsoft.Extensions.Options;
+using TestClasses.OptionsValidation;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class OptionsValidationTests
+{
+ [Fact]
+ public void RequiredAttributeValid()
+ {
+ var validModel = new RequiredAttributeModel
+ {
+ Val = "val"
+ };
+
+ var modelValidator = new RequiredAttributeModelValidator();
+ var result = modelValidator.Validate(nameof(validModel), validModel);
+
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Fact]
+ public void RequiredAttributeInvalid()
+ {
+ var validModel = new RequiredAttributeModel
+ {
+ Val = null
+ };
+
+ var modelValidator = new RequiredAttributeModelValidator();
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1);
+ }
+
+ [Fact]
+ public void RegularExpressionAttributeValid()
+ {
+ var validModel = new RegularExpressionAttributeModel
+ {
+ Val = " "
+ };
+
+ var modelValidator = new RegularExpressionAttributeModelValidator();
+ var result = modelValidator.Validate(nameof(validModel), validModel);
+
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Fact]
+ public void RegularExpressionAttributeInvalid()
+ {
+ var validModel = new RegularExpressionAttributeModel
+ {
+ Val = "Not Space"
+ };
+
+ var modelValidator = new RegularExpressionAttributeModelValidator();
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1);
+ }
+
+ [Fact]
+ public void EmailAttributeValid()
+ {
+ var validModel = new EmailAttributeModel
+ {
+ Val = "abc@xyz.com"
+ };
+
+ var modelValidator = new EmailAttributeModelValidator();
+ var result = modelValidator.Validate(nameof(validModel), validModel);
+
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Fact]
+ public void EmailAttributeInvalid()
+ {
+ var validModel = new EmailAttributeModel
+ {
+ Val = "Not Email Address"
+ };
+
+ var modelValidator = new EmailAttributeModelValidator();
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1);
+ }
+
+ [Fact]
+ public void CustomValidationAttributeValid()
+ {
+ var validModel = new CustomValidationAttributeModel
+ {
+ Val = "Pass"
+ };
+
+ var modelValidator = new CustomValidationAttributeModelValidator();
+ var result = modelValidator.Validate(nameof(validModel), validModel);
+
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Fact]
+ public void CustomValidationAttributeInvalid()
+ {
+ var validModel = new CustomValidationAttributeModel
+ {
+ Val = "NOT PASS"
+ };
+
+ var modelValidator = new CustomValidationAttributeModelValidator();
+ Assert.Throws<ValidationException>(() => modelValidator.Validate(nameof(validModel), validModel));
+ }
+
+ [Fact]
+ public void DataTypeAttributeValid()
+ {
+ var validModel = new DataTypeAttributeModel
+ {
+ Val = "ABC"
+ };
+
+ var modelValidator = new DataTypeAttributeModelValidator();
+ var result = modelValidator.Validate(nameof(validModel), validModel);
+
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Fact]
+ public void RangeAttributeModelIntValid()
+ {
+ var validModel = new RangeAttributeModelInt
+ {
+ Val = 1
+ };
+
+ var modelValidator = new RangeAttributeModelIntValidator();
+ var result = modelValidator.Validate(nameof(validModel), validModel);
+
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Fact]
+ public void RangeAttributeModelIntInvalid()
+ {
+ var validModel = new RangeAttributeModelInt
+ {
+ Val = 0
+ };
+
+ var modelValidator = new RangeAttributeModelIntValidator();
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1);
+ }
+
+ [Fact]
+ public void RangeAttributeModelDoubleValid()
+ {
+ var validModel = new RangeAttributeModelDouble
+ {
+ Val = 0.6
+ };
+
+ var modelValidator = new RangeAttributeModelDoubleValidator();
+ var result = modelValidator.Validate(nameof(validModel), validModel);
+
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Fact]
+ public void RangeAttributeModelDoubleInvalid()
+ {
+ var validModel = new RangeAttributeModelDouble
+ {
+ Val = 0.1
+ };
+
+ var modelValidator = new RangeAttributeModelDoubleValidator();
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1);
+ }
+
+ [Fact]
+ public void RangeAttributeModelDateValid()
+ {
+#if NETCOREAPP3_1_OR_GREATER
+ // Setting non-invariant culture to check that
+ // attribute's "ParseLimitsInInvariantCulture" property
+ // was set up correctly in the validator:
+ CultureInfo.CurrentCulture = new CultureInfo("cs");
+#else
+ // Setting invariant culture to avoid DateTime parsing discrepancies:
+ CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
+#endif
+ var validModel = new RangeAttributeModelDate
+ {
+ Val = new DateTime(day: 3, month: 1, year: 2004)
+ };
+
+ var modelValidator = new RangeAttributeModelDateValidator();
+ var result = modelValidator.Validate(nameof(validModel), validModel);
+
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Fact]
+ public void RangeAttributeModelDateInvalid()
+ {
+ var validModel = new RangeAttributeModelDate
+ {
+ Val = new DateTime(day: 1, month: 1, year: 2004)
+ };
+
+ var modelValidator = new RangeAttributeModelDateValidator();
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1);
+ }
+
+ [Fact]
+ public void MultipleAttributeModelValid()
+ {
+ var validModel = new MultipleAttributeModel
+ {
+ Val1 = "abc",
+ Val2 = 2,
+ Val3 = 4,
+ Val4 = 6
+ };
+
+ var modelValidator = new MultipleAttributeModelValidator();
+ var result = modelValidator.Validate(nameof(validModel), validModel);
+
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Theory]
+ [InlineData("", 2, 4, 7)]
+ [InlineData(null, 2, 4, 7)]
+ [InlineData("abc", 0, 4, 9)]
+ [InlineData("abc", 2, 8, 8)]
+ [InlineData("abc", 2, 4, 10)]
+ public void MultipleAttributeModelInvalid(string val1, int val2, int val3, int val4)
+ {
+ var validModel = new MultipleAttributeModel
+ {
+ Val1 = val1,
+ Val2 = val2,
+ Val3 = val3,
+ Val4 = val4
+ };
+
+ var modelValidator = new MultipleAttributeModelValidator();
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1);
+ }
+
+ [Fact]
+ public void CustomTypeCustomValidationAttributeModelValid()
+ {
+ var validModel = new CustomTypeCustomValidationAttributeModel
+ {
+ Val = new CustomType { Val1 = "Pass", Val2 = "Pass" }
+ };
+
+ var modelValidator = new CustomTypeCustomValidationAttributeModelValidator();
+ var result = modelValidator.Validate(nameof(validModel), validModel);
+
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Fact]
+ public void CustomTypeCustomValidationAttributeModelInvalid()
+ {
+ var validModel = new CustomTypeCustomValidationAttributeModel
+ {
+ Val = new CustomType { Val1 = "Pass", Val2 = "Not Pass" }
+ };
+
+ var modelValidator = new CustomTypeCustomValidationAttributeModelValidator();
+ Assert.Throws<ValidationException>(() => modelValidator.Validate(nameof(validModel), validModel));
+ }
+
+ [Fact]
+ public void DerivedModelIsValid()
+ {
+ var validModel = new DerivedModel
+ {
+ Val = 1,
+ DerivedVal = "Valid",
+ VirtualValWithAttr = 1,
+ VirtualValWithoutAttr = null
+ };
+
+ ((RequiredAttributeModel)validModel).Val = "Valid hidden member from base class";
+
+ var validator = new DerivedModelValidator();
+ var result = validator.Validate(nameof(validModel), validModel);
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Theory]
+ [InlineData(0, "", 1, null, "Valid hidden member from base class")]
+ [InlineData(null, "Valid", 1, null, "Valid hidden member from base class")]
+ [InlineData(1, "Valid", null, null, "Valid hidden member from base class")]
+ public void DerivedModelIsInvalid(int? val, string? derivedVal, int? virtValAttr, int? virtVal, string? hiddenValBaseClass)
+ {
+ var invalidModel = new DerivedModel
+ {
+ Val = val,
+ DerivedVal = derivedVal,
+ VirtualValWithAttr = virtValAttr,
+ VirtualValWithoutAttr = virtVal
+ };
+
+ ((RequiredAttributeModel)invalidModel).Val = hiddenValBaseClass;
+
+ var validator = new DerivedModelValidator();
+ Utils.VerifyValidateOptionsResult(validator.Validate(nameof(invalidModel), invalidModel), 1);
+ }
+
+ [Fact]
+ public void LeafModelIsValid()
+ {
+ var validModel = new LeafModel
+ {
+ Val = 1,
+ DerivedVal = "Valid",
+ VirtualValWithAttr = null,
+ VirtualValWithoutAttr = 1
+ };
+
+ ((RequiredAttributeModel)validModel).Val = "Valid hidden member from base class";
+
+ var validator = new LeafModelValidator();
+ var result = validator.Validate(nameof(validModel), validModel);
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Fact]
+ public void ComplexModelValid()
+ {
+ var validModel = new ComplexModel
+ {
+ ComplexVal = new RequiredAttributeModel { Val = "Valid" }
+ };
+
+ var modelValidator = new ComplexModelValidator();
+ var result = modelValidator.Validate(nameof(validModel), validModel);
+ Assert.Equal(ValidateOptionsResult.Success, result);
+
+ validModel = new ComplexModel
+ {
+ ValWithoutOptionsValidator = new TypeWithoutOptionsValidator
+ {
+ Val1 = "Valid",
+ Val2 = new DateTime(day: 3, month: 1, year: 2004)
+ }
+ };
+
+ // Setting invariant culture to avoid DateTime parsing discrepancies:
+ CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
+ result = modelValidator.Validate(nameof(validModel), validModel);
+ Assert.Equal(ValidateOptionsResult.Success, result);
+
+ validModel = new ComplexModel
+ {
+ ValWithoutOptionsValidator = new TypeWithoutOptionsValidator
+ {
+ Val1 = "A",
+ Val2 = new DateTime(day: 2, month: 2, year: 2004),
+ YetAnotherComplexVal = new RangeAttributeModelDouble { Val = 0.7 }
+ }
+ };
+
+ result = modelValidator.Validate(nameof(validModel), validModel);
+ Assert.Equal(ValidateOptionsResult.Success, result);
+ }
+
+ [Fact]
+ public void ComplexModelInvalid()
+ {
+ var invalidModel = new ComplexModel
+ {
+ ComplexVal = new RequiredAttributeModel { Val = null }
+ };
+
+ var modelValidator = new ComplexModelValidator();
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(invalidModel), invalidModel), 1);
+
+ invalidModel = new ComplexModel
+ {
+ ValWithoutOptionsValidator = new TypeWithoutOptionsValidator { Val1 = "Valid", Val2 = new DateTime(2003, 3, 3) }
+ };
+
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(invalidModel), invalidModel), 1);
+
+ invalidModel = new ComplexModel
+ {
+ ValWithoutOptionsValidator = new TypeWithoutOptionsValidator { Val1 = string.Empty, Val2 = new DateTime(2004, 3, 3) }
+ };
+
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(invalidModel), invalidModel), 1);
+
+ invalidModel = new ComplexModel
+ {
+ ValWithoutOptionsValidator = new TypeWithoutOptionsValidator
+ {
+ Val1 = "A",
+ Val2 = new DateTime(2004, 2, 2),
+ YetAnotherComplexVal = new RangeAttributeModelDouble { Val = 0.4999 }
+ }
+ };
+
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(invalidModel), invalidModel), 1);
+ }
+
+ [Fact]
+ public void AttributePropertyModelTestOnErrorMessage()
+ {
+ var validModel = new AttributePropertyModel
+ {
+ Val1 = 5,
+ Val2 = 1
+ };
+
+ var modelValidator = new AttributePropertyModelValidator();
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1);
+ }
+
+ [Fact]
+ public void AttributePropertyModelTestOnErrorMessageResource()
+ {
+ var validModel = new AttributePropertyModel
+ {
+ Val1 = 1,
+ Val2 = 5
+ };
+
+ var modelValidator = new AttributePropertyModelValidator();
+ Utils.VerifyValidateOptionsResult(modelValidator.Validate(nameof(validModel), validModel), 1);
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Options;
+using RandomMembers;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class RandomMembersTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var firstModel = new FirstModel
+ {
+ P1 = "1234",
+ };
+
+ var validator = new FirstValidator();
+ var vr = validator.Validate("RandomMembers", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 1, "P1");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var firstModel = new FirstModel
+ {
+ P1 = "12345",
+ };
+
+ var validator = new FirstValidator();
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("RandomMembers", firstModel));
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#if ROSLYN_4_0_OR_GREATER
+
+using Microsoft.Extensions.Options;
+using RecordTypes;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class RecordTypesTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var thirdModel = new ThirdModel
+ {
+ P6 = "1234",
+ };
+
+ var secondModel = new SecondModel
+ {
+ P5 = "1234",
+ };
+
+ var firstModel = new FirstModel
+ {
+ P1 = "1234",
+ P2 = secondModel,
+ P3 = secondModel,
+ P4 = thirdModel,
+ };
+
+ var validator = default(FirstValidator);
+ var vr = validator.Validate("RecordTypes", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 4, "P1", "P2.P5", "P3.P5", "P4.P6");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var thirdModel = new ThirdModel
+ {
+ P6 = "12345",
+ };
+
+ var secondModel = new SecondModel
+ {
+ P5 = "12345",
+ };
+
+ var firstModel = new FirstModel
+ {
+ P1 = "12345",
+ P2 = secondModel,
+ P3 = secondModel,
+ P4 = thirdModel,
+ };
+
+ var validator = default(FirstValidator);
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("RecordTypes", firstModel));
+ }
+}
+
+#endif
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Options;
+using RepeatedTypes;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class RepeatedTypesTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var thirdModel = new ThirdModel
+ {
+ P5 = "1234",
+ };
+
+ var secondModel = new SecondModel
+ {
+ P4 = thirdModel,
+ };
+
+ var firstModel = new FirstModel
+ {
+ P1 = secondModel,
+ P2 = secondModel,
+ P3 = thirdModel,
+ };
+
+ var validator = new FirstValidator();
+ var vr = validator.Validate("RepeatedTypes", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 3, "P1.P4.P5", "P2.P4.P5", "P3.P5");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var thirdModel = new ThirdModel
+ {
+ P5 = "12345",
+ };
+
+ var secondModel = new SecondModel
+ {
+ P4 = thirdModel,
+ };
+
+ var firstModel = new FirstModel
+ {
+ P1 = secondModel,
+ P2 = secondModel,
+ P3 = thirdModel,
+ };
+
+ var validator = new FirstValidator();
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("RepeatedTypes", firstModel));
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Options;
+using SelfValidation;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class SelfValidationTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var firstModel = new FirstModel
+ {
+ P1 = "1234",
+ };
+
+ var validator = default(FirstValidator);
+ var vr = validator.Validate("SelfValidation", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 1, "P1");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var firstModel = new FirstModel
+ {
+ P1 = "12345",
+ };
+
+ var validator = default(FirstValidator);
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("SelfValidation", firstModel));
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#if NETCOREAPP3_1_OR_GREATER
+using System.Linq;
+#endif
+using Microsoft.Extensions.Options;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+internal static class Utils
+{
+ public static void VerifyValidateOptionsResult(ValidateOptionsResult vr, int expectedErrorCount, params string[] expectedErrorSubstrings)
+ {
+ Assert.NotNull(vr);
+
+#if NETCOREAPP3_1_OR_GREATER
+ var failures = vr.Failures!.ToArray();
+#else
+ var failures = vr.FailureMessage!.Split(';');
+#endif
+
+ Assert.Equal(expectedErrorCount, failures.Length);
+
+ for (int i = 0; i < expectedErrorSubstrings.Length; i++)
+ {
+ Assert.Contains(expectedErrorSubstrings[i], failures[i]);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Options;
+using ValueTypes;
+using Xunit;
+
+namespace Microsoft.Gen.OptionsValidation.Test;
+
+public class ValueTypesTests
+{
+ [Fact]
+ public void Invalid()
+ {
+ var secondModel = new SecondModel
+ {
+ P4 = "1234",
+ };
+
+ var firstModel = new FirstModel
+ {
+ P1 = "1234",
+ P3 = secondModel,
+ P2 = secondModel,
+ P4 = default,
+ };
+
+ var validator = default(FirstValidator);
+ var vr = validator.Validate("ValueTypes", firstModel);
+
+ Utils.VerifyValidateOptionsResult(vr, 3, "P1", "P2.P4", "P3.P4");
+ }
+
+ [Fact]
+ public void Valid()
+ {
+ var secondModel = new SecondModel
+ {
+ P4 = "12345",
+ };
+
+ var firstModel = new FirstModel
+ {
+ P1 = "12345",
+ P3 = secondModel,
+ P2 = secondModel,
+ P4 = default,
+ };
+
+ var validator = default(FirstValidator);
+ Assert.Equal(ValidateOptionsResult.Success, validator.Validate("ValueTypes", firstModel));
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFrameworks>$(NetCoreAppCurrent);$(NetFrameworkMinimum)</TargetFrameworks>
+ <RoslynApiVersion>$(MicrosoftCodeAnalysisVersion_4_4)</RoslynApiVersion>
+ <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
+ <!-- <CompilerGeneratedFilesOutputPath>$(OutputPath)/$(TargetFramework)/Generated</CompilerGeneratedFilesOutputPath> -->
+ <EnableDefaultItems>true</EnableDefaultItems>
+ <!-- <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> -->
+ <DefineConstants>$(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER;ROSLYN_4_0_OR_GREATER</DefineConstants>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="$(CoreLibSharedDir)System\Runtime\CompilerServices\IsExternalInit.cs" Link="Common\System\Runtime\CompilerServices\IsExternalInit.cs" />
+ <Compile Include="$(CommonPath)System\ThrowHelper.cs" Link="Common\System\ThrowHelper.cs" />
+ <Compile Include="$(CommonPath)..\tests\SourceGenerators\RoslynTestUtils.cs" Link="SourceGenerators\RoslynTestUtils.cs" />
+
+ <Compile Include="$(LibrariesProjectRoot)Microsoft.Extensions.Options\gen\DiagDescriptorsBase.cs" Link="gen\DiagDescriptorsBase.cs" />
+ <Compile Include="$(LibrariesProjectRoot)Microsoft.Extensions.Options\gen\DiagDescriptors.cs" Link="gen\DiagDescriptors.cs" />
+ <Compile Remove="Baselines\**\*.cs" />
+ </ItemGroup>
+
+ <ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETFramework'">
+ <ProjectReference Include="$(LibrariesProjectRoot)System.ComponentModel.Annotations\src\System.ComponentModel.Annotations.csproj" SkipUseReferenceAssembly="true" />
+ </ItemGroup>
+
+ <ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
+ <Reference Include="System.ComponentModel.DataAnnotations" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.CodeAnalysis" Version="$(MicrosoftCodeAnalysisVersion)" />
+ <ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Options\src\Microsoft.Extensions.Options.csproj" SkipUseReferenceAssembly="true" />
+ <ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Options\gen\Microsoft.Extensions.Options.SourceGeneration.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="true" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Content Include="TestClasses\**\*">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+
+ <Content Include="Baselines\**\*">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ </ItemGroup>
+
+ <Target Name="FixIncrementalCoreCompileWithAnalyzers" BeforeTargets="CoreCompile">
+ <ItemGroup>
+ <CustomAdditionalCompileInputs Include="@(Analyzer)" />
+ </ItemGroup>
+ </Target>
+
+ <!-- <Target Name="MakeMyDir" AfterTargets="PrepareForBuild">
+ <MakeDir Directories="$(OutputPath)/$(TargetFramework)/Generated" Condition="!Exists('$(OutputPath)/$(TargetFramework)/Generated')" />
+ </Target> -->
+</Project>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="ErrorMessageResourceName" xml:space="preserve">
+ <value>ErrorMessageResourceName</value>
+ </data>
+ <data name="CantUseWithGenericTypesTitle" xml:space="preserve">
+ <value>Can't use 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' on fields or properties with open generic types.</value>
+ </data>
+ <data name="PotentiallyMissingEnumerableValidationMessage" xml:space="preserve">
+ <value>Type {0} has validation annotations, but member {1} doesn't specify [ValidateEnumeratedItems] which could be an oversight.</value>
+ </data>
+ <data name="PotentiallyMissingEnumerableValidationTitle" xml:space="preserve">
+ <value>Member potentially missing enumerable validation.</value>
+ </data>
+ <data name="PotentiallyMissingTransitiveValidationMessage" xml:space="preserve">
+ <value>Type {0} has validation annotations, but member {1} doesn't specify [ValidateObjectMembers] which could be an oversight.</value>
+ </data>
+ <data name="CircularTypeReferencesMessage" xml:space="preserve">
+ <value>There is a circular type reference involving type {0} preventing it from being used for static validation.</value>
+ </data>
+ <data name="CircularTypeReferencesTitle" xml:space="preserve">
+ <value>Unsupported circular references in model types.</value>
+ </data>
+ <data name="MemberIsInaccessibleMessage" xml:space="preserve">
+ <value>Can't apply validation attributes to private field or property {0}.</value>
+ </data>
+ <data name="NotEnumerableTypeMessage" xml:space="preserve">
+ <value>[ValidateEnumeratedItems] cannot be used on members of type {0} as it doesn't implement IEnumerable<T>.</value>
+ </data>
+ <data name="NullValidatorTypeTitle" xml:space="preserve">
+ <value>Null validator type specified for the 'ValidateObjectMembersAttribute' or 'ValidateEnumeratedItemsAttribute' attributes.</value>
+ </data>
+ <data name="CantUseWithGenericTypesMessage" xml:space="preserve">
+ <value>Can't use [ValidateObjectMembers] or [ValidateEnumeratedItems] on fields or properties with open generic type {0}.</value>
+ </data>
+ <data name="NoEligibleMemberTitle" xml:space="preserve">
+ <value>A member type has no fields or properties to validate.</value>
+ </data>
+ <data name="NoEligibleMembersFromValidatorTitle" xml:space="preserve">
+ <value>A type has no fields or properties to validate.</value>
+ </data>
+ <data name="NotEnumerableTypeTitle" xml:space="preserve">
+ <value>Member type is not enumerable.</value>
+ </data>
+ <data name="ValidatorsNeedSimpleConstructorMessage" xml:space="preserve">
+ <value>Validator type {0} doesn't have a parameterless constructor.</value>
+ </data>
+ <data name="DoesntImplementIValidateOptionsMessage" xml:space="preserve">
+ <value>Type {0} does not implement the required IValidateOptions<{1}> interface.</value>
+ </data>
+ <data name="ValidatorsNeedSimpleConstructorTitle" xml:space="preserve">
+ <value>Validators used for transitive or enumerable validation must have a constructor with no parameters.</value>
+ </data>
+ <data name="NoEligibleMembersFromValidatorMessage" xml:space="preserve">
+ <value>Type {0} has no fields or properties to validate, referenced by type {1}.</value>
+ </data>
+ <data name="NoEligibleMemberMessage" xml:space="preserve">
+ <value>Type {0} has no fields or properties to validate, referenced from member {1}.</value>
+ </data>
+ <data name="DoesntImplementIValidateOptionsTitle" xml:space="preserve">
+ <value>A type annotated with 'OptionsValidatorAttribute' doesn't implement the necessary interface.</value>
+ </data>
+ <data name="MemberIsInaccessibleTitle" xml:space="preserve">
+ <value>Can't validate private fields or properties.</value>
+ </data>
+ <data name="CantBeStaticClassMessage" xml:space="preserve">
+ <value>[OptionsValidator] cannot be applied to static class {0}.</value>
+ </data>
+ <data name="AlreadyImplementsValidateMethodTitle" xml:space="preserve">
+ <value>A type already includes an implementation of the 'Validate' method.</value>
+ </data>
+ <data name="AlreadyImplementsValidateMethodMessage" xml:space="preserve">
+ <value>Type {0} already implements the Validate method.</value>
+ </data>
+ <data name="CantBeStaticClassTitle" xml:space="preserve">
+ <value>'OptionsValidatorAttribute' can't be applied to a static class.</value>
+ </data>
+ <data name="NullValidatorTypeMessage" xml:space="preserve">
+ <value>Null validator type specified in [ValidateObjectMembers] or [ValidateEnumeratedItems] attributes.</value>
+ </data>
+ <data name="PotentiallyMissingTransitiveValidationTitle" xml:space="preserve">
+ <value>Member potentially missing transitive validation.</value>
+ </data>
+</root>
\ No newline at end of file
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+
+namespace CustomAttr
+{
+#pragma warning disable SA1649
+#pragma warning disable SA1402
+#pragma warning disable CA1019
+#pragma warning disable IDE0052
+
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
+ public sealed class CustomAttribute : ValidationAttribute
+ {
+ private readonly char _ch;
+ private readonly bool _caseSensitive;
+ private readonly string? _extra;
+
+ public CustomAttribute(char ch, bool caseSensitive, string? extra)
+ {
+ _ch = ch;
+ _caseSensitive = caseSensitive;
+ _extra = extra;
+ }
+
+ protected override ValidationResult IsValid(object? value, ValidationContext? validationContext)
+ {
+ if (value == null)
+ {
+ return ValidationResult.Success!;
+ }
+
+ if (_caseSensitive)
+ {
+ if ((char)value != _ch)
+ {
+ return new ValidationResult($"{validationContext?.MemberName} didn't match");
+ }
+ }
+ else
+ {
+ if (char.ToUpperInvariant((char)value) != char.ToUpperInvariant(_ch))
+ {
+ return new ValidationResult($"{validationContext?.MemberName} didn't match");
+ }
+ }
+
+ return ValidationResult.Success!;
+ }
+ }
+
+ public class FirstModel
+ {
+ [Custom('A', true, null)]
+ public char P1 { get; set; }
+
+ [Custom('A', false, "X")]
+ public char P2 { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.Extensions.Options;
+
+namespace Enumeration
+{
+#pragma warning disable SA1649
+#pragma warning disable SA1402
+
+ public class FirstModel
+ {
+ [ValidateEnumeratedItems]
+ public IList<SecondModel>? P1;
+
+ [ValidateEnumeratedItems(typeof(SecondValidator))]
+ public IList<SecondModel>? P2;
+
+ [ValidateEnumeratedItems]
+ public IList<SecondModel?>? P3;
+
+ [ValidateEnumeratedItems]
+ public IList<ThirdModel>? P4;
+
+ [ValidateEnumeratedItems]
+ public IList<ThirdModel?>? P5;
+
+ [ValidateEnumeratedItems]
+ [SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1125:Use shorthand for nullable types", Justification = "Testing System>Nullable<T>")]
+ public IList<Nullable<ThirdModel>>? P51;
+
+ [ValidateEnumeratedItems]
+ public SynteticEnumerable? P6;
+
+ [ValidateEnumeratedItems]
+ public SynteticEnumerable P7;
+
+ [ValidateEnumeratedItems]
+ [SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1125:Use shorthand for nullable types", Justification = "Testing System>Nullable<T>")]
+ public Nullable<SynteticEnumerable> P8;
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P6 = string.Empty;
+ }
+
+ public struct ThirdModel
+ {
+ [Range(0, 10)]
+ public int Value;
+ }
+
+ public struct SynteticEnumerable : IEnumerable<SecondModel>
+ {
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
+ public IEnumerator<SecondModel> GetEnumerator() => new InternalEnumerator();
+
+ private class InternalEnumerator : IEnumerator<SecondModel>
+ {
+ public SecondModel Current => throw new NotSupportedException();
+
+ object IEnumerator.Current => Current;
+
+ public void Dispose()
+ {
+ // Nothing to dispose...
+ }
+
+ public bool MoveNext() => false;
+
+ public void Reset() => throw new NotSupportedException();
+ }
+ }
+
+ [OptionsValidator]
+ public partial struct FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial struct SecondValidator : IValidateOptions<SecondModel>
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+
+namespace Fields
+{
+#pragma warning disable SA1649
+#pragma warning disable SA1402
+#pragma warning disable S1186
+#pragma warning disable CA1822
+
+ public class FirstModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P1 = string.Empty;
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(SecondValidator))]
+ public SecondModel? P2;
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers]
+ public ThirdModel P3;
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P4 = string.Empty;
+ }
+
+ public struct ThirdModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P5 = string.Empty;
+
+ public int P6 = default;
+
+ public ThirdModel(object _)
+ {
+ }
+ }
+
+ [OptionsValidator]
+ public partial struct FirstValidator : IValidateOptions<FirstModel>
+ {
+ public void Validate()
+ {
+ }
+
+ public void Validate(int _)
+ {
+ }
+
+ public void Validate(string? _)
+ {
+ }
+
+ public void Validate(string? _0, object _1)
+ {
+ }
+ }
+
+ [OptionsValidator]
+ public partial struct SecondValidator : IValidateOptions<SecondModel>
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+
+namespace FileScopedNamespace;
+
+#pragma warning disable SA1649 // File name should match first type name
+
+public class FirstModel
+{
+ [Required]
+ [MinLength(5)]
+ public string P1 = string.Empty;
+}
+
+[OptionsValidator]
+public partial struct FirstValidator : IValidateOptions<FirstModel>
+{
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+
+namespace FunnyStrings
+{
+#pragma warning disable SA1649
+#pragma warning disable SA1402
+
+ public class FirstModel
+ {
+ [RegularExpression("\"\r\n\\\\")]
+ public string P1 { get; set; } = string.Empty;
+ }
+
+ [OptionsValidator]
+ public partial struct FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+
+namespace Generics
+{
+#pragma warning disable SA1649
+#pragma warning disable SA1402
+
+ public class FirstModel<T>
+ {
+ [Required]
+ [MinLength(5)]
+ public string P1 { get; set; } = string.Empty;
+
+ public T? P2 { get; set; }
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers]
+ public SecondModel? P3 { get; set; }
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P4 { get; set; } = string.Empty;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator<T> : IValidateOptions<FirstModel<T>>
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+using Microsoft.Gen.OptionsValidation.Test;
+
+#pragma warning disable SA1649
+#pragma warning disable SA1402
+
+namespace TestClasses.OptionsValidation
+{
+ // ValidationAttribute without parameter
+ public class RequiredAttributeModel
+ {
+ [Required]
+ public string? Val { get; set; }
+ }
+
+ // ValidationAttribute with string parameter
+ public class RegularExpressionAttributeModel
+ {
+ [RegularExpression("\\s")]
+ public string Val { get; set; } = string.Empty;
+ }
+
+ // DataTypeAttribute
+ public class EmailAttributeModel
+ {
+ [EmailAddress]
+ public string Val { get; set; } = string.Empty;
+ }
+
+ // ValidationAttribute with System.Type parameter
+ public class CustomValidationAttributeModel
+ {
+ [CustomValidation(typeof(CustomValidationTest), "TestMethod")]
+ public string Val { get; set; } = string.Empty;
+ }
+
+#pragma warning disable SA1204 // Static elements should appear before instance elements
+ public static class CustomValidationTest
+#pragma warning restore SA1204 // Static elements should appear before instance elements
+ {
+ public static ValidationResult? TestMethod(string val, ValidationContext _)
+ {
+ if (val.Equals("Pass", StringComparison.Ordinal))
+ {
+ return ValidationResult.Success;
+ }
+
+ throw new ValidationException();
+ }
+ }
+
+ // ValidationAttribute with DataType parameter
+ public class DataTypeAttributeModel
+ {
+ [DataType(DataType.Text)]
+ public string Val { get; set; } = string.Empty;
+ }
+
+ // ValidationAttribute with type, double, int parameters
+ public class RangeAttributeModelInt
+ {
+ [Range(1, 3)]
+ public int Val { get; set; }
+ }
+
+ public class RangeAttributeModelDouble
+ {
+ [Range(0.5, 0.9)]
+ public double Val { get; set; }
+ }
+
+ public class RangeAttributeModelDate
+ {
+#if NETCOREAPP3_1_OR_GREATER
+ [Range(typeof(DateTime), "1/2/2004", "3/4/2004", ParseLimitsInInvariantCulture = true)]
+#else
+ [Range(typeof(DateTime), "1/2/2004", "3/4/2004")]
+#endif
+ public DateTime Val { get; set; }
+ }
+
+ public class MultipleAttributeModel
+ {
+ [Required]
+ [DataType(DataType.Password)]
+ public string Val1 { get; set; } = string.Empty;
+
+ [Range(1, 3)]
+ public int Val2 { get; set; }
+
+ [Range(3, 5)]
+ public int Val3 { get; set; }
+
+ [Range(5, 9)]
+ public int Val4 { get; set; }
+ }
+
+ public class CustomTypeCustomValidationAttributeModel
+ {
+ [CustomValidation(typeof(CustomTypeCustomValidationTest), "TestMethod")]
+ public CustomType? Val { get; set; }
+ }
+
+ public class CustomType
+ {
+ public string Val1 { get; set; } = string.Empty;
+ public string Val2 { get; set; } = string.Empty;
+ }
+
+#pragma warning disable SA1204 // Static elements should appear before instance elements
+ public static class CustomTypeCustomValidationTest
+#pragma warning restore SA1204 // Static elements should appear before instance elements
+ {
+ public static ValidationResult? TestMethod(CustomType val, ValidationContext _)
+ {
+ if (val.Val1.Equals("Pass", StringComparison.Ordinal) && val.Val2.Equals("Pass", StringComparison.Ordinal))
+ {
+ return ValidationResult.Success;
+ }
+
+ throw new ValidationException();
+ }
+ }
+
+ public class AttributePropertyModel
+ {
+ [Range(1, 3, ErrorMessage = "ErrorMessage")]
+ public int Val1 { get; set; }
+
+ [Range(1, 3, ErrorMessageResourceType = typeof(SR), ErrorMessageResourceName = "ErrorMessageResourceName")]
+ public int Val2 { get; set; }
+ }
+
+ public class TypeWithoutOptionsValidator
+ {
+ [Required]
+ public string? Val1 { get; set; }
+
+ [Range(typeof(DateTime), "1/2/2004", "3/4/2004")]
+ public DateTime Val2 { get; set; }
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers]
+ public RangeAttributeModelDouble? YetAnotherComplexVal { get; set; }
+ }
+
+ public class DerivedModel : RequiredAttributeModel
+ {
+ [Required]
+ public string? DerivedVal { get; set; }
+
+ [Required]
+ internal virtual int? VirtualValWithAttr { get; set; }
+
+ public virtual int? VirtualValWithoutAttr { get; set; }
+
+ [Required]
+ public new int? Val { get; set; }
+ }
+
+ public class LeafModel : DerivedModel
+ {
+ internal override int? VirtualValWithAttr { get; set; }
+
+ [Required]
+ public override int? VirtualValWithoutAttr { get; set; }
+ }
+
+ public class ComplexModel
+ {
+ [Microsoft.Extensions.Options.ValidateObjectMembers]
+ public RequiredAttributeModel? ComplexVal { get; set; }
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers]
+ public TypeWithoutOptionsValidator? ValWithoutOptionsValidator { get; set; }
+ }
+
+ [OptionsValidator]
+ public partial class RequiredAttributeModelValidator : IValidateOptions<RequiredAttributeModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class RegularExpressionAttributeModelValidator : IValidateOptions<RegularExpressionAttributeModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class EmailAttributeModelValidator : IValidateOptions<EmailAttributeModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class CustomValidationAttributeModelValidator : IValidateOptions<CustomValidationAttributeModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class DataTypeAttributeModelValidator : IValidateOptions<DataTypeAttributeModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class RangeAttributeModelIntValidator : IValidateOptions<RangeAttributeModelInt>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class RangeAttributeModelDoubleValidator : IValidateOptions<RangeAttributeModelDouble>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class RangeAttributeModelDateValidator : IValidateOptions<RangeAttributeModelDate>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class MultipleAttributeModelValidator : IValidateOptions<MultipleAttributeModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class CustomTypeCustomValidationAttributeModelValidator : IValidateOptions<CustomTypeCustomValidationAttributeModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class AttributePropertyModelValidator : IValidateOptions<AttributePropertyModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class DerivedModelValidator : IValidateOptions<DerivedModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial class LeafModelValidator : IValidateOptions<LeafModel>
+ {
+ }
+
+ [OptionsValidator]
+ internal sealed partial class ComplexModelValidator : IValidateOptions<ComplexModel>
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+
+namespace MultiModelValidator
+{
+#pragma warning disable SA1649
+#pragma warning disable SA1402
+
+ public class FirstModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P1 = string.Empty;
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(MultiValidator))]
+ public SecondModel? P2;
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P3 = string.Empty;
+ }
+
+ [OptionsValidator]
+ public partial struct MultiValidator : IValidateOptions<FirstModel>, IValidateOptions<SecondModel>
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+// #if ROSLYN_4_0_OR_GREATER
+// #if ROSLYN4_0_OR_GREATER
+
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+
+namespace Nested
+{
+#pragma warning disable SA1649
+#pragma warning disable SA1402
+
+ public static class Container1
+ {
+ public class FirstModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P1 { get; set; } = string.Empty;
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(Container2.Container3.SecondValidator))]
+ public SecondModel? P2 { get; set; }
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers]
+ public ThirdModel P3 { get; set; }
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(Container4.Container5.ThirdValidator))]
+ public SecondModel? P4 { get; set; }
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P5 { get; set; } = string.Empty;
+ }
+
+ public struct ThirdModel
+ {
+ public ThirdModel(int _)
+ {
+ }
+
+ [Required]
+ [MinLength(5)]
+ public string P6 { get; set; } = string.Empty;
+ }
+ }
+
+ public static partial class Container2
+ {
+ public partial class Container3
+ {
+ public Container3(int _)
+ {
+ // nothing to do
+ }
+
+ [OptionsValidator]
+ public partial struct FirstValidator : IValidateOptions<Container1.FirstModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial struct SecondValidator : IValidateOptions<Container1.SecondModel>
+ {
+ }
+ }
+ }
+
+ public partial record class Container4
+ {
+ public partial record class Container5
+ {
+ public Container5(int _)
+ {
+ // nothing to do
+ }
+
+ [OptionsValidator]
+ public partial struct ThirdValidator : IValidateOptions<Container1.SecondModel>
+ {
+ }
+ }
+ }
+
+ public partial struct Container6
+ {
+ [OptionsValidator]
+ public partial struct FourthValidator : IValidateOptions<Container1.SecondModel>
+ {
+ }
+ }
+
+ public partial record struct Container7
+ {
+ [OptionsValidator]
+ public partial record struct FifthValidator : IValidateOptions<Container1.SecondModel>
+ {
+ }
+ }
+}
+
+// #endif
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+
+#pragma warning disable SA1649
+#pragma warning disable SA1402
+
+public class FirstModelNoNamespace
+{
+ [Required]
+ [MinLength(5)]
+ public string P1 { get; set; } = string.Empty;
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(SecondValidatorNoNamespace))]
+ public SecondModelNoNamespace? P2 { get; set; }
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers]
+ public ThirdModelNoNamespace? P3 { get; set; }
+}
+
+public class SecondModelNoNamespace
+{
+ [Required]
+ [MinLength(5)]
+ public string P4 { get; set; } = string.Empty;
+}
+
+public class ThirdModelNoNamespace
+{
+ [Required]
+ [MinLength(5)]
+ public string P5 { get; set; } = string.Empty;
+}
+
+[OptionsValidator]
+public partial class FirstValidatorNoNamespace : IValidateOptions<FirstModelNoNamespace>
+{
+}
+
+[OptionsValidator]
+public partial class SecondValidatorNoNamespace : IValidateOptions<SecondModelNoNamespace>
+{
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+
+namespace RandomMembers
+{
+#pragma warning disable SA1649
+#pragma warning disable SA1402
+#pragma warning disable CA1822
+
+ public class FirstModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string? P1 { get; set; }
+
+ public void Foo()
+ {
+ throw new NotSupportedException();
+ }
+
+ public class Nested
+ {
+ }
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+// #if ROSLYN_4_0_OR_GREATER
+
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+
+namespace RecordTypes
+{
+#pragma warning disable SA1649
+
+ public record class FirstModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P1 { get; set; } = string.Empty;
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(SecondValidator))]
+ public SecondModel? P2 { get; set; }
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers(typeof(ThirdValidator))]
+ public SecondModel P3 { get; set; } = new SecondModel();
+
+ [Microsoft.Extensions.Options.ValidateObjectMembers]
+ public ThirdModel P4 { get; set; }
+ }
+
+ public record class SecondModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P5 { get; set; } = string.Empty;
+ }
+
+ public record struct ThirdModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P6 { get; set; } = string.Empty;
+
+ public ThirdModel(int _)
+ {
+ }
+
+ public ThirdModel(object _)
+ {
+ }
+ }
+
+ [OptionsValidator]
+ public partial record struct FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial record struct SecondValidator : IValidateOptions<SecondModel>
+ {
+ }
+
+ [OptionsValidator]
+ public partial record class ThirdValidator : IValidateOptions<SecondModel>
+ {
+ }
+}
+
+// #endif
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+
+namespace RepeatedTypes
+{
+#pragma warning disable SA1649
+#pragma warning disable SA1402
+#pragma warning disable CA1019
+
+ public class FirstModel
+ {
+ [Required]
+ [Microsoft.Extensions.Options.ValidateObjectMembers]
+ public SecondModel? P1 { get; set; }
+
+ [Required]
+ [Microsoft.Extensions.Options.ValidateObjectMembers]
+ public SecondModel? P2 { get; set; }
+
+ [Required]
+ [Microsoft.Extensions.Options.ValidateObjectMembers]
+ public ThirdModel? P3 { get; set; }
+ }
+
+ public class SecondModel
+ {
+ [Required]
+ [Microsoft.Extensions.Options.ValidateObjectMembers]
+ public ThirdModel? P4 { get; set; }
+ }
+
+ public class ThirdModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string? P5;
+ }
+
+ [OptionsValidator]
+ public partial class FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using Microsoft.Extensions.Options;
+
+namespace SelfValidation
+{
+#pragma warning disable SA1649
+
+ public class FirstModel : IValidatableObject
+ {
+ [Required]
+ public string P1 = string.Empty;
+
+ public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
+ {
+ if (P1.Length < 5)
+ {
+ return new[] { new ValidationResult("P1 is not long enough") };
+ }
+
+ return Array.Empty<ValidationResult>();
+ }
+ }
+
+ [OptionsValidator]
+ public partial struct FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.Extensions.Options;
+
+namespace ValueTypes
+{
+#pragma warning disable SA1649
+
+ public class FirstModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P1 { get; set; } = string.Empty;
+
+ [ValidateObjectMembers]
+ public SecondModel? P2 { get; set; }
+
+ [ValidateObjectMembers]
+ public SecondModel P3 { get; set; }
+
+ [ValidateObjectMembers]
+ [SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1125:Use shorthand for nullable types", Justification = "Testing System>Nullable<T>")]
+ public Nullable<SecondModel> P4 { get; set; }
+ }
+
+ public struct SecondModel
+ {
+ [Required]
+ [MinLength(5)]
+ public string P4 { get; set; } = string.Empty;
+
+ public SecondModel(object _)
+ {
+ }
+ }
+
+ [OptionsValidator]
+ public partial struct FirstValidator : IValidateOptions<FirstModel>
+ {
+ }
+}