mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-09 17:44:48 +09:00
Options validation source generator (#87587)
This commit is contained in:
parent
7f4334efd5
commit
de6f07edd2
78 changed files with 12224 additions and 1 deletions
|
@ -235,7 +235,24 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL
|
|||
| __`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****`)
|
||||
|
||||
|
|
|
@ -31,6 +31,46 @@ namespace System
|
|||
[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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
387
src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs
Normal file
387
src/libraries/Microsoft.Extensions.Options/gen/Emitter.cs
Normal file
|
@ -0,0 +1,387 @@
|
|||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
111
src/libraries/Microsoft.Extensions.Options/gen/EmitterBase.cs
Normal file
111
src/libraries/Microsoft.Extensions.Options/gen/EmitterBase.cs
Normal file
|
@ -0,0 +1,111 @@
|
|||
// 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();
|
||||
}
|
||||
}
|
53
src/libraries/Microsoft.Extensions.Options/gen/Generator.cs
Normal file
53
src/libraries/Microsoft.Extensions.Options/gen/Generator.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<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>
|
|
@ -0,0 +1,20 @@
|
|||
// 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);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// 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);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// 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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// 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);
|
||||
}
|
664
src/libraries/Microsoft.Extensions.Options/gen/Parser.cs
Normal file
664
src/libraries/Microsoft.Extensions.Options/gen/Parser.cs
Normal file
|
@ -0,0 +1,664 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
// 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,137 @@
|
|||
<?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>
|
|
@ -0,0 +1,20 @@
|
|||
// 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);
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -215,6 +215,10 @@ namespace Microsoft.Extensions.Options
|
|||
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) { }
|
||||
|
@ -282,6 +286,20 @@ namespace Microsoft.Extensions.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;
|
||||
|
|
|
@ -30,4 +30,10 @@
|
|||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\gen\Microsoft.Extensions.Options.SourceGeneration.csproj"
|
||||
ReferenceOutputAssembly="false"
|
||||
PackAsAnalyzer="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// 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
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// 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; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// 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; }
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,37 @@
|
|||
<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>
|
|
@ -0,0 +1,201 @@
|
|||
<?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>
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,59 @@
|
|||
// 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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// 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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
// 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;
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
// 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()})");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
// 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
|
|
@ -0,0 +1,60 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,442 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
// 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
|
|
@ -0,0 +1,61 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// 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]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// 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));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
<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>
|
|
@ -0,0 +1,201 @@
|
|||
<?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>
|
|
@ -0,0 +1,68 @@
|
|||
// 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>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
// 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>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
// 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>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// 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>
|
||||
{
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// 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>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// 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>>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
// 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>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// 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>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
// 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
|
|
@ -0,0 +1,45 @@
|
|||
// 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>
|
||||
{
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// 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>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
// 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
|
|
@ -0,0 +1,46 @@
|
|||
// 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>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// 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>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// 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>
|
||||
{
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue