diff --git a/src/FluentValidation/BitzArt.FluentValidation.Extensions/ActionTypes.cs b/src/FluentValidation/BitzArt.FluentValidation.Extensions/ActionTypes.cs
new file mode 100644
index 0000000..ef0fea3
--- /dev/null
+++ b/src/FluentValidation/BitzArt.FluentValidation.Extensions/ActionTypes.cs
@@ -0,0 +1,16 @@
+namespace FluentValidation;
+
+public static class ActionTypes
+{
+ public const string Get = "Get";
+
+ public const string Create = "Create";
+
+ public const string Update = "Update";
+
+ public const string Patch = "Patch";
+
+ public const string Options = "Options";
+
+ public const string Delete = "Delete";
+}
diff --git a/src/FluentValidation/BitzArt.FluentValidation.Extensions/BitzArt.FluentValidation.Extensions.csproj b/src/FluentValidation/BitzArt.FluentValidation.Extensions/BitzArt.FluentValidation.Extensions.csproj
index f896082..2e29046 100644
--- a/src/FluentValidation/BitzArt.FluentValidation.Extensions/BitzArt.FluentValidation.Extensions.csproj
+++ b/src/FluentValidation/BitzArt.FluentValidation.Extensions/BitzArt.FluentValidation.Extensions.csproj
@@ -16,6 +16,7 @@
+
diff --git a/src/FluentValidation/BitzArt.FluentValidation.Extensions/Enums/ActionType.cs b/src/FluentValidation/BitzArt.FluentValidation.Extensions/Enums/ActionType.cs
index b6f44fe..daa7797 100644
--- a/src/FluentValidation/BitzArt.FluentValidation.Extensions/Enums/ActionType.cs
+++ b/src/FluentValidation/BitzArt.FluentValidation.Extensions/Enums/ActionType.cs
@@ -1,11 +1,24 @@
-namespace FluentValidation;
+using System.Runtime.Serialization;
+
+namespace FluentValidation;
public enum ActionType : byte
{
+ [EnumMember(Value = ActionTypes.Get)]
Get = 1,
+
+ [EnumMember(Value = ActionTypes.Create)]
Create = 2,
+
+ [EnumMember(Value = ActionTypes.Update)]
Update = 3,
+
+ [EnumMember(Value = ActionTypes.Patch)]
Patch = 4,
+
+ [EnumMember(Value = ActionTypes.Options)]
Options = 5,
+
+ [EnumMember(Value = ActionTypes.Delete)]
Delete = 6
}
diff --git a/src/FluentValidation/BitzArt.FluentValidation.Extensions/Extensions/AddActionValidatorsExtension.cs b/src/FluentValidation/BitzArt.FluentValidation.Extensions/Extensions/AddActionValidatorsExtension.cs
index e56808a..f9b43df 100644
--- a/src/FluentValidation/BitzArt.FluentValidation.Extensions/Extensions/AddActionValidatorsExtension.cs
+++ b/src/FluentValidation/BitzArt.FluentValidation.Extensions/Extensions/AddActionValidatorsExtension.cs
@@ -1,17 +1,19 @@
-using Microsoft.Extensions.DependencyInjection;
+using BitzArt.EnumToMemberValue;
+using Microsoft.Extensions.DependencyInjection;
+using System;
using System.Reflection;
namespace FluentValidation;
public static class AddActionValidatorsExtension
{
- public static IServiceCollection AddActionValidatorsFromAssemblyContaining(this IServiceCollection services, Func getActionType)
+ public static IServiceCollection AddActionValidatorsFromAssemblyContaining(this IServiceCollection services, Func? getActionType = null)
=> services.AddActionValidatorsFromAssemblyContaining(typeof(TAssemblyPointer), getActionType);
- public static IServiceCollection AddActionValidatorsFromAssemblyContaining(this IServiceCollection services, Type type, Func getActionType)
+ public static IServiceCollection AddActionValidatorsFromAssemblyContaining(this IServiceCollection services, Type type, Func? getActionType = null)
=> services.AddActionValidatorsFromAssembly(type.Assembly, getActionType);
- public static IServiceCollection AddActionValidatorsFromAssembly(this IServiceCollection services, Assembly assembly, Func getActionType)
+ public static IServiceCollection AddActionValidatorsFromAssembly(this IServiceCollection services, Assembly assembly, Func? getActionType = null)
{
var validators = assembly
.DefinedTypes
@@ -23,7 +25,7 @@ public static IServiceCollection AddActionValidatorsFromAssembly(this IServiceCo
return services;
}
- public static IServiceCollection AddActionValidator(this IServiceCollection services, Type validatorType, Func getActionType)
+ public static IServiceCollection AddActionValidator(this IServiceCollection services, Type validatorType, Func? getActionType = null)
{
if (validatorType is null) throw new ArgumentException($"{nameof(validatorType)} must not be null");
if (validatorType.BaseType!.GetGenericTypeDefinition() != typeof(ActionValidator<>)) throw new ArgumentException($"{validatorType.Name} is not assignable to ActionValidator");
@@ -34,13 +36,61 @@ public static IServiceCollection AddActionValidator(this IServiceCollection serv
var registrationType = typeof(IValidator<>).MakeGenericType(validationObjectType);
services.AddTransient(validatorType);
- services.AddScoped(registrationType, x =>
+
+ if (getActionType is not null) services.AddScoped(registrationType, x =>
{
var validator = x.GetRequiredService(validatorType);
(validator as IActionValidator)!.ActionType = getActionType.Invoke(x);
return validator;
});
+ services.AddKeyedForEnum(
+ registrationType,
+ x => (IActionValidator)x.GetRequiredService(validatorType),
+ (ActionType type) => type.ToMemberValue(),
+ (validator, key) => validator.ActionType = key,
+ ServiceLifetime.Scoped);
+
return services;
}
+
+ private static void AddKeyedForEnum(
+ this IServiceCollection services,
+ Type registrationType,
+ Func implementationFactory,
+ Func enumStringValueFactory,
+ Action applyKeyAction,
+ ServiceLifetime serviceLifetime)
+ where TService : class
+ where TEnum : struct, Enum
+ {
+ var enumValues = Enum.GetValues();
+
+ foreach (var enumValue in enumValues)
+ {
+ services.Add(
+ new ServiceDescriptor(
+ registrationType,
+ enumValue,
+ (x, key) =>
+ {
+ var service = implementationFactory(x);
+ applyKeyAction(service, enumValue);
+ return service;
+ },
+ serviceLifetime));
+
+ services.Add(
+ new ServiceDescriptor(
+ registrationType,
+ enumStringValueFactory(enumValue),
+ (x, key) =>
+ {
+ var service = implementationFactory(x);
+ applyKeyAction(service, enumValue);
+ return service;
+ },
+ serviceLifetime));
+ }
+ }
}
diff --git a/tests/FluentValidation/BitzArt.FluentValidation.Extensions.UnitTests/Tests/AddActionValidatorsExtensionTests.cs b/tests/FluentValidation/BitzArt.FluentValidation.Extensions.UnitTests/Tests/AddActionValidatorsExtensionTests.cs
index 1b76adb..341efa4 100644
--- a/tests/FluentValidation/BitzArt.FluentValidation.Extensions.UnitTests/Tests/AddActionValidatorsExtensionTests.cs
+++ b/tests/FluentValidation/BitzArt.FluentValidation.Extensions.UnitTests/Tests/AddActionValidatorsExtensionTests.cs
@@ -1,3 +1,4 @@
+using BitzArt.EnumToMemberValue;
using FluentValidation.Models;
using Microsoft.Extensions.DependencyInjection;
@@ -107,4 +108,81 @@ public void AddActionValidatorsFromAssemblyContainingGeneric_WithFlatActionType_
var validatorCasted = (TestEntityValidator)validator;
Assert.Equal(actionType, validatorCasted.ActionType);
}
+
+ [Theory]
+ [InlineData(ActionType.Get)]
+ [InlineData(ActionType.Create)]
+ [InlineData(ActionType.Update)]
+ [InlineData(ActionType.Patch)]
+ [InlineData(ActionType.Options)]
+ [InlineData(ActionType.Delete)]
+ public void AddActionValidator_WithoutSpecifyingActionType_ValidatorAccessibleByActionType(ActionType resolveKey)
+ {
+ // Arrange
+ IServiceCollection services = new ServiceCollection();
+ var validatorType = typeof(TestEntityValidator);
+
+ // Act
+ services.AddActionValidator(validatorType);
+
+ // Assert
+ var serviceProvider = services.BuildServiceProvider();
+ var validator = serviceProvider.GetRequiredKeyedService>(resolveKey);
+
+ Assert.NotNull(validator);
+ Assert.True(validator is TestEntityValidator);
+ Assert.Equal(resolveKey, ((TestEntityValidator)validator).ActionType);
+ }
+
+ [Theory]
+ [InlineData(ActionType.Get)]
+ [InlineData(ActionType.Create)]
+ [InlineData(ActionType.Update)]
+ [InlineData(ActionType.Patch)]
+ [InlineData(ActionType.Options)]
+ [InlineData(ActionType.Delete)]
+ public void AddActionValidator_WithActionType_ValidatorStillAccessibleByActionType(ActionType resolveKey)
+ {
+ // Arrange
+ IServiceCollection services = new ServiceCollection();
+ var validatorType = typeof(TestEntityValidator);
+
+ // Act
+ services.AddActionValidator(validatorType, x => default);
+
+ // Assert
+ var serviceProvider = services.BuildServiceProvider();
+ var validator = serviceProvider.GetRequiredKeyedService>(resolveKey);
+
+ Assert.NotNull(validator);
+ Assert.True(validator is TestEntityValidator);
+ Assert.Equal(resolveKey, ((TestEntityValidator)validator).ActionType);
+ }
+
+ [Theory]
+ [InlineData(ActionTypes.Get)]
+ [InlineData(ActionTypes.Create)]
+ [InlineData(ActionTypes.Update)]
+ [InlineData(ActionTypes.Patch)]
+ [InlineData(ActionTypes.Options)]
+ [InlineData(ActionTypes.Delete)]
+ public void AddActionValidator_WithoutSpecifyingActionType_ValidatorAccessibleByActionTypeEnumMemberValue(string resolveKey)
+ {
+ // Arrange
+ IServiceCollection services = new ServiceCollection();
+ var validatorType = typeof(TestEntityValidator);
+
+ // Act
+ services.AddActionValidator(validatorType);
+
+ // Assert
+ var serviceProvider = services.BuildServiceProvider();
+ var validator = serviceProvider.GetRequiredKeyedService>(resolveKey);
+
+ var expectedActionType = resolveKey.ToEnum();
+
+ Assert.NotNull(validator);
+ Assert.True(validator is TestEntityValidator);
+ Assert.Equal(expectedActionType, ((TestEntityValidator)validator).ActionType);
+ }
}
\ No newline at end of file