From bb695c630e5313610c0f6b0cfdcb32559950db7e Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 25 Nov 2021 16:13:07 +0800 Subject: [PATCH] Add `IValueValidatorFactory` Resolve #10724 --- ...ureManagementApplicationContractsModule.cs | 9 +++++- ...reManagementApplicationContractsOptions.cs | 21 +++++++++++++ .../JsonConverters/IValueValidatorFactory.cs | 10 +++++++ .../NewtonsoftStringValueTypeJsonConverter.cs | 20 ++++++++----- .../StringValueTypeJsonConverter.cs | 9 +++++- .../JsonConverters/ValueValidatorFactory.cs | 24 +++++++++++++++ .../ValueValidatorJsonConverter.cs | 19 +++++++----- .../AbpFeatureManagementHttpApiModule.cs | 3 +- ...ewtonsoftStringValueJsonConverter_Tests.cs | 2 +- .../StringValueJsonConverter_Tests.cs | 23 ++++++++++++++ ...mTextJsonStringValueJsonConverter_Tests.cs | 2 +- .../FeatureManagement/UrlValueValidator.cs | 30 +++++++++++++++++++ 12 files changed, 153 insertions(+), 19 deletions(-) create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsOptions.cs create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/IValueValidatorFactory.cs create mode 100644 modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorFactory.cs create mode 100644 modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/UrlValueValidator.cs diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs index daf82df6ad..6e16177bab 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Application; using Volo.Abp.Authorization; using Volo.Abp.FeatureManagement.JsonConverters; @@ -25,6 +26,11 @@ public class AbpFeatureManagementApplicationContractsModule : AbpModule options.FileSets.AddEmbedded(); }); + Configure(options => + { + context.Services.ExecutePreConfiguredActions(options); + }); + Configure(options => { options.Converters.Add(); @@ -32,7 +38,8 @@ public class AbpFeatureManagementApplicationContractsModule : AbpModule Configure(options => { - options.JsonSerializerOptions.Converters.AddIfNotContains(new StringValueTypeJsonConverter()); + var contractsOptions = context.Services.ExecutePreConfiguredActions(); + options.JsonSerializerOptions.Converters.AddIfNotContains(new StringValueTypeJsonConverter(contractsOptions)); }); } } diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsOptions.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsOptions.cs new file mode 100644 index 0000000000..98f531c6a2 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsOptions.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using Volo.Abp.FeatureManagement.JsonConverters; +using Volo.Abp.Validation.StringValues; + +namespace Volo.Abp.FeatureManagement; + +public class AbpFeatureManagementApplicationContractsOptions +{ + public HashSet ValueValidatorFactory { get; } + + public AbpFeatureManagementApplicationContractsOptions() + { + ValueValidatorFactory = new HashSet + { + new ValueValidatorFactory("NULL"), + new ValueValidatorFactory("BOOLEAN"), + new ValueValidatorFactory("NUMERIC"), + new ValueValidatorFactory("STRING") + }; + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/IValueValidatorFactory.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/IValueValidatorFactory.cs new file mode 100644 index 0000000000..9428dfb031 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/IValueValidatorFactory.cs @@ -0,0 +1,10 @@ +using Volo.Abp.Validation.StringValues; + +namespace Volo.Abp.FeatureManagement.JsonConverters; + +public interface IValueValidatorFactory +{ + bool CanCreate(string name); + + IValueValidator Create(); +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/NewtonsoftStringValueTypeJsonConverter.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/NewtonsoftStringValueTypeJsonConverter.cs index c85e48d0f3..aa9a913718 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/NewtonsoftStringValueTypeJsonConverter.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/NewtonsoftStringValueTypeJsonConverter.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Extensions.Options; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Volo.Abp.DependencyInjection; @@ -13,6 +14,13 @@ public class NewtonsoftStringValueTypeJsonConverter : JsonConverter, ITransientD { public override bool CanWrite => false; + protected readonly AbpFeatureManagementApplicationContractsOptions Options; + + public NewtonsoftStringValueTypeJsonConverter(IOptions options) + { + Options = options.Value; + } + public override bool CanConvert(Type objectType) { return objectType == typeof(IStringValueType); @@ -77,13 +85,11 @@ public class NewtonsoftStringValueTypeJsonConverter : JsonConverter, ITransientD protected virtual IValueValidator CreateValueValidatorByName(JToken jObject, string name) { - return name switch + foreach (var factory in Options.ValueValidatorFactory.Where(factory => factory.CanCreate(name))) { - "NULL" => new AlwaysValidValueValidator(), - "BOOLEAN" => new BooleanValueValidator(), - "NUMERIC" => new NumericValueValidator(), - "STRING" => new StringValueValidator(), - _ => throw new ArgumentException($"{nameof(IValueValidator)} named {name} was not found!") - }; + return factory.Create(); + } + + throw new ArgumentException($"{nameof(IValueValidator)} named {name} was cannot be created!"); } } diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/StringValueTypeJsonConverter.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/StringValueTypeJsonConverter.cs index 3148224914..f2632a3e2b 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/StringValueTypeJsonConverter.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/StringValueTypeJsonConverter.cs @@ -8,6 +8,13 @@ namespace Volo.Abp.FeatureManagement.JsonConverters; public class StringValueTypeJsonConverter : JsonConverter { + protected readonly AbpFeatureManagementApplicationContractsOptions Options; + + public StringValueTypeJsonConverter(AbpFeatureManagementApplicationContractsOptions options) + { + Options = options; + } + public override IStringValueType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var rootElement = JsonDocument.ParseValue(ref reader).RootElement; @@ -17,7 +24,7 @@ public class StringValueTypeJsonConverter : JsonConverter { var name = nameJsonProperty.Value.GetString(); - var newOptions = JsonSerializerOptionsHelper.Create(options, this, new ValueValidatorJsonConverter(), + var newOptions = JsonSerializerOptionsHelper.Create(options, this, new ValueValidatorJsonConverter(Options), new SelectionStringValueItemSourceJsonConverter()); return name switch diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorFactory.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorFactory.cs new file mode 100644 index 0000000000..ae52cd43dd --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorFactory.cs @@ -0,0 +1,24 @@ +using Volo.Abp.Validation.StringValues; + +namespace Volo.Abp.FeatureManagement.JsonConverters; + +public class ValueValidatorFactory : IValueValidatorFactory + where TValueValidator : IValueValidator, new() +{ + protected readonly string Name; + + public ValueValidatorFactory(string name) + { + Name = name; + } + + public bool CanCreate(string name) + { + return Name == name; + } + + public IValueValidator Create() + { + return new TValueValidator() as IValueValidator; + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs index 31f6dc290a..c53563e7ee 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs @@ -10,6 +10,13 @@ namespace Volo.Abp.FeatureManagement.JsonConverters; public class ValueValidatorJsonConverter : JsonConverter { + protected readonly AbpFeatureManagementApplicationContractsOptions Options; + + public ValueValidatorJsonConverter(AbpFeatureManagementApplicationContractsOptions options) + { + Options = options; + } + public override IValueValidator Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var rootElement = JsonDocument.ParseValue(ref reader).RootElement; @@ -47,13 +54,11 @@ public class ValueValidatorJsonConverter : JsonConverter protected virtual IValueValidator CreateValueValidatorByName(string name) { - return name switch + foreach (var factory in Options.ValueValidatorFactory.Where(factory => factory.CanCreate(name))) { - "NULL" => new AlwaysValidValueValidator(), - "BOOLEAN" => new BooleanValueValidator(), - "NUMERIC" => new NumericValueValidator(), - "STRING" => new StringValueValidator(), - _ => throw new ArgumentException($"{nameof(IValueValidator)} named {name} was not found!") - }; + return factory.Create(); + } + + throw new ArgumentException($"{nameof(IValueValidator)} named {name} was cannot be created!"); } } diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo/Abp/FeatureManagement/AbpFeatureManagementHttpApiModule.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo/Abp/FeatureManagement/AbpFeatureManagementHttpApiModule.cs index 1963c60fd5..6c88d39933 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo/Abp/FeatureManagement/AbpFeatureManagementHttpApiModule.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.HttpApi/Volo/Abp/FeatureManagement/AbpFeatureManagementHttpApiModule.cs @@ -34,7 +34,8 @@ public class AbpFeatureManagementHttpApiModule : AbpModule Configure(options => { - options.JsonSerializerOptions.Converters.AddIfNotContains(new StringValueTypeJsonConverter()); + var contractsOptions = context.Services.ExecutePreConfiguredActions(); + options.JsonSerializerOptions.Converters.AddIfNotContains(new StringValueTypeJsonConverter(contractsOptions)); }); } } diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/NewtonsoftStringValueJsonConverter_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/NewtonsoftStringValueJsonConverter_Tests.cs index a778a8717b..09f3c2266d 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/NewtonsoftStringValueJsonConverter_Tests.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/NewtonsoftStringValueJsonConverter_Tests.cs @@ -9,7 +9,7 @@ public class NewtonsoftStringValueJsonConverter_Tests : StringValueJsonConverter { services.PreConfigure(options => { - options.UseHybridSerializer = true; + options.UseHybridSerializer = false; }); } } diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/StringValueJsonConverter_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/StringValueJsonConverter_Tests.cs index 137a8d0c13..28b8e55052 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/StringValueJsonConverter_Tests.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/StringValueJsonConverter_Tests.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; using Shouldly; +using Volo.Abp.FeatureManagement.JsonConverters; using Volo.Abp.Json; using Volo.Abp.Validation.StringValues; using Xunit; @@ -16,6 +18,16 @@ public abstract class StringValueJsonConverter_Tests : FeatureManagementApplicat _jsonSerializer = GetRequiredService(); } + protected override void BeforeAddApplication(IServiceCollection services) + { + services.PreConfigure(options => + { + options.ValueValidatorFactory.Add(new ValueValidatorFactory("URL")); + }); + + base.BeforeAddApplication(services); + } + [Fact] public void Should_Serialize_And_Deserialize() { @@ -67,6 +79,13 @@ public abstract class StringValueJsonConverter_Tests : FeatureManagementApplicat Name = "FeatureName", Key = "FeatureKey" } + }, + new FeatureDto + { + ValueType = new FreeTextStringValueType + { + Validator = new UrlValueValidator("https") + } } } } @@ -95,5 +114,9 @@ public abstract class StringValueJsonConverter_Tests : FeatureManagementApplicat featureListDto2.Groups[0].Features[3].Provider.Name.ShouldBe("FeatureName"); featureListDto2.Groups[0].Features[3].Provider.Key.ShouldBe("FeatureKey"); + + featureListDto2.Groups[0].Features[4].ValueType.ShouldBeOfType(); + featureListDto2.Groups[0].Features[4].ValueType.Validator.ShouldBeOfType(); + featureListDto2.Groups[0].Features[4].ValueType.Validator.As().Scheme.ShouldBe("https"); } } diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/SystemTextJsonStringValueJsonConverter_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/SystemTextJsonStringValueJsonConverter_Tests.cs index b4791c46cd..968055c09f 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/SystemTextJsonStringValueJsonConverter_Tests.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/SystemTextJsonStringValueJsonConverter_Tests.cs @@ -9,7 +9,7 @@ public class SystemTextJsonStringValueJsonConverter_Tests : StringValueJsonConve { services.PreConfigure(options => { - options.UseHybridSerializer = false; + options.UseHybridSerializer = true; }); } } diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/UrlValueValidator.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/UrlValueValidator.cs new file mode 100644 index 0000000000..6b29edcb2a --- /dev/null +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/UrlValueValidator.cs @@ -0,0 +1,30 @@ +using System; +using Volo.Abp.Validation.StringValues; + +namespace Volo.Abp.FeatureManagement; + +[Serializable] +[ValueValidator("URL")] +public class UrlValueValidator : ValueValidatorBase +{ + public string Scheme { + get => this["Scheme"].ToString(); + set => this["Scheme"] = value; + } + + public UrlValueValidator() + { + + } + + public UrlValueValidator(string scheme) + { + Scheme = scheme; + } + + public override bool IsValid(object value) + { + var s = value.ToString(); + return s != null && s.StartsWith(Scheme); + } +}