From 01a226cde03210967ecd1f4f8c4a20e6427edeba Mon Sep 17 00:00:00 2001 From: nadia Date: Mon, 4 Mar 2024 12:34:17 +0500 Subject: [PATCH 1/5] feat: add SkipGraphValidationAttribute --- .../Graph/FluentGraphValidator.cs | 6 ++++++ .../SkipGraphValidationAttribute.cs | 4 ++++ tests/Sitko.FluentValidation.Tests/Data/BarModel.cs | 4 ++++ .../FluentGraphValidatorTests.cs | 13 +++++++++++++ 4 files changed, 27 insertions(+) create mode 100644 src/Sitko.FluentValidation/SkipGraphValidationAttribute.cs diff --git a/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs b/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs index 0328b17..3287ee7 100644 --- a/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs +++ b/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs @@ -166,6 +166,12 @@ or char or uint or ulong or short or sbyte || foreach (var property in modelGraphValidationContext.Model.GetType().GetProperties()) { + var attr = property.GetCustomAttributes(typeof(SkipGraphValidationAttribute), true).Cast() + .FirstOrDefault(); + if (attr != null) + { + continue; + } var propertyModel = property.GetValue(modelGraphValidationContext.Model); diff --git a/src/Sitko.FluentValidation/SkipGraphValidationAttribute.cs b/src/Sitko.FluentValidation/SkipGraphValidationAttribute.cs new file mode 100644 index 0000000..4d9cefb --- /dev/null +++ b/src/Sitko.FluentValidation/SkipGraphValidationAttribute.cs @@ -0,0 +1,4 @@ +namespace Sitko.FluentValidation; + +[AttributeUsage(AttributeTargets.Property)] +public class SkipGraphValidationAttribute : Attribute; diff --git a/tests/Sitko.FluentValidation.Tests/Data/BarModel.cs b/tests/Sitko.FluentValidation.Tests/Data/BarModel.cs index be3ffb8..915c93f 100644 --- a/tests/Sitko.FluentValidation.Tests/Data/BarModel.cs +++ b/tests/Sitko.FluentValidation.Tests/Data/BarModel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Sitko.FluentValidation.Tests.Data; @@ -7,4 +8,7 @@ public class BarModel public Guid TestGuid { get; set; } = Guid.Empty; public BarType Type { get; set; } = BarType.Bar; public int Val { get; set; } + + [SkipGraphValidation] + public List FooModels { get; set; } = new(); } diff --git a/tests/Sitko.FluentValidation.Tests/FluentGraphValidatorTests.cs b/tests/Sitko.FluentValidation.Tests/FluentGraphValidatorTests.cs index c97cfa0..520b6b6 100644 --- a/tests/Sitko.FluentValidation.Tests/FluentGraphValidatorTests.cs +++ b/tests/Sitko.FluentValidation.Tests/FluentGraphValidatorTests.cs @@ -17,6 +17,19 @@ public FluentGraphValidatorTests(ITestOutputHelper testOutputHelper) : base(test { } + [Fact] + public async Task Validate() + { + var scope = await GetScopeAsync(); + var validator = scope.GetService(); + + var bar = new BarModel { Val = 0, FooModels = new List { new() { Id = Guid.NewGuid() } } }; + var foo = new FooModel { Id = Guid.NewGuid(), BarModels = new List { bar } }; + + var result = await validator.TryValidateModelAsync(foo); + result.Results.Where(r => r.Model.GetType() == typeof(FooModel)).Should().ContainSingle(); + } + [Fact] public async Task ValidateParent() { From b08fe559d91a9de6eee691488a23964b8183ead0 Mon Sep 17 00:00:00 2001 From: nadia Date: Mon, 4 Mar 2024 12:49:13 +0500 Subject: [PATCH 2/5] feat: support .net8 --- .../Sitko.FluentValidation.csproj | 14 ++++++++++-- .../FluentGraphValidatorTests.cs | 2 +- .../Sitko.FluentValidation.Tests.csproj | 4 ++-- .../ValidationTestScope.cs | 22 +++++++++---------- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/Sitko.FluentValidation/Sitko.FluentValidation.csproj b/src/Sitko.FluentValidation/Sitko.FluentValidation.csproj index 24e138f..b2fe813 100644 --- a/src/Sitko.FluentValidation/Sitko.FluentValidation.csproj +++ b/src/Sitko.FluentValidation/Sitko.FluentValidation.csproj @@ -1,7 +1,7 @@ - netstandard2.0;netstandard2.1;net6.0;net7.0 + netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0 enable enable latest @@ -22,11 +22,21 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + diff --git a/tests/Sitko.FluentValidation.Tests/FluentGraphValidatorTests.cs b/tests/Sitko.FluentValidation.Tests/FluentGraphValidatorTests.cs index 520b6b6..9b02406 100644 --- a/tests/Sitko.FluentValidation.Tests/FluentGraphValidatorTests.cs +++ b/tests/Sitko.FluentValidation.Tests/FluentGraphValidatorTests.cs @@ -18,7 +18,7 @@ public FluentGraphValidatorTests(ITestOutputHelper testOutputHelper) : base(test } [Fact] - public async Task Validate() + public async Task ValidateSkipAttribute() { var scope = await GetScopeAsync(); var validator = scope.GetService(); diff --git a/tests/Sitko.FluentValidation.Tests/Sitko.FluentValidation.Tests.csproj b/tests/Sitko.FluentValidation.Tests/Sitko.FluentValidation.Tests.csproj index a1f362d..6525827 100644 --- a/tests/Sitko.FluentValidation.Tests/Sitko.FluentValidation.Tests.csproj +++ b/tests/Sitko.FluentValidation.Tests/Sitko.FluentValidation.Tests.csproj @@ -1,13 +1,13 @@ - net6.0;net7.0 + net8.0 enable false - + diff --git a/tests/Sitko.FluentValidation.Tests/ValidationTestScope.cs b/tests/Sitko.FluentValidation.Tests/ValidationTestScope.cs index 43a339a..8071a4c 100644 --- a/tests/Sitko.FluentValidation.Tests/ValidationTestScope.cs +++ b/tests/Sitko.FluentValidation.Tests/ValidationTestScope.cs @@ -1,4 +1,4 @@ -using Sitko.Core.App; +using Microsoft.Extensions.Hosting; using Sitko.FluentValidation.Graph; namespace Sitko.FluentValidation.Tests; @@ -11,23 +11,21 @@ namespace Sitko.FluentValidation.Tests; [UsedImplicitly] public class ValidationTestScope : BaseTestScope { - protected override IServiceCollection ConfigureServices(IApplicationContext applicationContext, - IServiceCollection services, string name) + protected override IHostApplicationBuilder ConfigureServices(IHostApplicationBuilder builder, string name) { - base.ConfigureServices(applicationContext, services, name); - services.AddFluentValidationExtensions(); - services.AddValidatorsFromAssemblyContaining(); - return services; + base.ConfigureServices(builder, name); + builder.Services.AddFluentValidationExtensions(); + builder.Services.AddValidatorsFromAssemblyContaining(); + return builder; } } public class ValidationWithExcludedPrefixTestScope : ValidationTestScope { - protected override IServiceCollection ConfigureServices(IApplicationContext applicationContext, - IServiceCollection services, string name) + protected override IHostApplicationBuilder ConfigureServices(IHostApplicationBuilder builder, string name) { - base.ConfigureServices(applicationContext, services, name); - services.Configure(options => options.NamespacePrefixes.Add("Sitko")); - return services; + base.ConfigureServices(builder, name); + builder.Services.Configure(options => options.NamespacePrefixes.Add("Sitko")); + return builder; } } From 8f03ebde0be3b4e3f43f408d92691dd001ae516e Mon Sep 17 00:00:00 2001 From: nadia Date: Mon, 4 Mar 2024 15:49:46 +0500 Subject: [PATCH 3/5] feat: cache skip attributes --- src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs b/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs index 3287ee7..2c98006 100644 --- a/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs +++ b/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs @@ -14,6 +14,7 @@ public class FluentGraphValidator : IFluentGraphValidator private readonly ILogger logger; private readonly IOptions options; private readonly IServiceScope serviceScope; + private readonly ConcurrentDictionary skipAttributes = new(); public FluentGraphValidator(IServiceProvider serviceProvider, ILogger logger, IOptions options) @@ -166,9 +167,10 @@ or char or uint or ulong or short or sbyte || foreach (var property in modelGraphValidationContext.Model.GetType().GetProperties()) { - var attr = property.GetCustomAttributes(typeof(SkipGraphValidationAttribute), true).Cast() - .FirstOrDefault(); - if (attr != null) + var needSkipAttribute = skipAttributes.GetOrAdd($"{modelGraphValidationContext.Model.GetType()}_{property.Name}", _ => property.GetCustomAttributes(typeof(SkipGraphValidationAttribute), true) + .Cast() + .FirstOrDefault() != null); + if (needSkipAttribute) { continue; } From 9f39aa427d7f72e9a84c0b4c3481ca6248fae7ee Mon Sep 17 00:00:00 2001 From: nadia Date: Mon, 4 Mar 2024 16:28:55 +0500 Subject: [PATCH 4/5] refactor: rename vars --- src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs b/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs index 2c98006..17e9039 100644 --- a/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs +++ b/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs @@ -14,7 +14,7 @@ public class FluentGraphValidator : IFluentGraphValidator private readonly ILogger logger; private readonly IOptions options; private readonly IServiceScope serviceScope; - private readonly ConcurrentDictionary skipAttributes = new(); + private static readonly ConcurrentDictionary IgnorePropertiesCache = new(); public FluentGraphValidator(IServiceProvider serviceProvider, ILogger logger, IOptions options) @@ -167,10 +167,10 @@ or char or uint or ulong or short or sbyte || foreach (var property in modelGraphValidationContext.Model.GetType().GetProperties()) { - var needSkipAttribute = skipAttributes.GetOrAdd($"{modelGraphValidationContext.Model.GetType()}_{property.Name}", _ => property.GetCustomAttributes(typeof(SkipGraphValidationAttribute), true) + var isSkippedProperty = IgnorePropertiesCache.GetOrAdd($"{modelGraphValidationContext.Model.GetType()}_{property.Name}", _ => property.GetCustomAttributes(typeof(SkipGraphValidationAttribute), true) .Cast() .FirstOrDefault() != null); - if (needSkipAttribute) + if (isSkippedProperty) { continue; } From 3b023dcf5520938941a8d3f67e5cb9e8ffe854ed Mon Sep 17 00:00:00 2001 From: nadia Date: Mon, 4 Mar 2024 16:31:34 +0500 Subject: [PATCH 5/5] refactor: rename to ignoredPropertiesCache --- src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs b/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs index 17e9039..d16d89f 100644 --- a/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs +++ b/src/Sitko.FluentValidation/Graph/FluentGraphValidator.cs @@ -14,7 +14,7 @@ public class FluentGraphValidator : IFluentGraphValidator private readonly ILogger logger; private readonly IOptions options; private readonly IServiceScope serviceScope; - private static readonly ConcurrentDictionary IgnorePropertiesCache = new(); + private static readonly ConcurrentDictionary IgnoredPropertiesCache = new(); public FluentGraphValidator(IServiceProvider serviceProvider, ILogger logger, IOptions options) @@ -167,7 +167,7 @@ or char or uint or ulong or short or sbyte || foreach (var property in modelGraphValidationContext.Model.GetType().GetProperties()) { - var isSkippedProperty = IgnorePropertiesCache.GetOrAdd($"{modelGraphValidationContext.Model.GetType()}_{property.Name}", _ => property.GetCustomAttributes(typeof(SkipGraphValidationAttribute), true) + var isSkippedProperty = IgnoredPropertiesCache.GetOrAdd($"{modelGraphValidationContext.Model.GetType()}_{property.Name}", _ => property.GetCustomAttributes(typeof(SkipGraphValidationAttribute), true) .Cast() .FirstOrDefault() != null); if (isSkippedProperty)