-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
85b7731
commit 315909f
Showing
13 changed files
with
324 additions
and
223 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
[*.{cs,vb}] | ||
|
||
# IDE0130: Namespace does not match folder structure | ||
dotnet_diagnostic.IDE0130.severity = none |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 0 additions & 16 deletions
16
src/FluentValidation/BitzArt.FluentValidation.Extensions/ActionTypes.cs
This file was deleted.
Oops, something went wrong.
10 changes: 1 addition & 9 deletions
10
src/FluentValidation/BitzArt.FluentValidation.Extensions/Enums/ActionType.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,16 @@ | ||
using System.Runtime.Serialization; | ||
|
||
namespace FluentValidation; | ||
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 | ||
} |
80 changes: 80 additions & 0 deletions
80
...Validation/BitzArt.FluentValidation.Extensions/Extensions/AddActionValidatorExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.DependencyInjection.Extensions; | ||
using System.Reflection; | ||
|
||
namespace FluentValidation; | ||
|
||
public static class AddActionValidatorExtensions | ||
{ | ||
public static IServiceCollection AddActionValidatorsFromAssemblyContaining<TAssemblyPointer>(this IServiceCollection services, Func<IServiceProvider, ActionType>? actionTypeResolver = null) | ||
=> services.AddActionValidatorsFromAssemblyContaining(typeof(TAssemblyPointer), actionTypeResolver); | ||
|
||
public static IServiceCollection AddActionValidatorsFromAssemblyContaining(this IServiceCollection services, Type type, Func<IServiceProvider, ActionType>? actionTypeResolver = null) | ||
=> services.AddActionValidatorsFromAssembly(type.Assembly, actionTypeResolver); | ||
|
||
public static IServiceCollection AddActionValidatorsFromAssembly(this IServiceCollection services, Assembly assembly, Func<IServiceProvider, ActionType>? actionTypeResolver = null) | ||
{ | ||
var validators = assembly | ||
.DefinedTypes | ||
.Where(x => x.IsClass && !x.IsAbstract) | ||
.Where(x => x.GetInterfaces() | ||
.Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IActionValidator<>))); | ||
|
||
foreach (var validator in validators) services.AddActionValidator(validator, actionTypeResolver); | ||
|
||
return services; | ||
} | ||
|
||
public static IServiceCollection AddActionValidator<TValidator>(this IServiceCollection services, Func<IServiceProvider, ActionType>? actionTypeResolver = null) | ||
=> services.AddActionValidator(typeof(TValidator), actionTypeResolver); | ||
|
||
public static IServiceCollection AddActionValidator(this IServiceCollection services, Type validatorType, Func<IServiceProvider, ActionType>? actionTypeResolver = 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"); | ||
|
||
services.TryAddScoped<IActionValidatorFactory>(serviceProvider => new ActionValidatorFactory(serviceProvider)); | ||
|
||
var interfaceDefinitions = validatorType.GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IActionValidator<>)).ToList(); | ||
if (interfaceDefinitions.Count == 0) throw new ArgumentException($"{validatorType.Name} does not implement IActionValidator<T>"); | ||
|
||
services.AddTransient(validatorType); | ||
ActionValidatorFactory.ValidatorTypeMap[validatorType] = validatorType; | ||
|
||
Func<IServiceProvider, ActionType?> finalActionTypeResolver = actionTypeResolver is not null ? | ||
x => actionTypeResolver(x) : | ||
x => null; | ||
|
||
foreach (var interfaceDefinition in interfaceDefinitions) | ||
{ | ||
var validationObjectType = interfaceDefinition.GetGenericArguments().First(); | ||
services.AddActionValidator(validatorType, validationObjectType, finalActionTypeResolver); | ||
} | ||
|
||
return services; | ||
} | ||
|
||
private static IServiceCollection AddActionValidator(this IServiceCollection services, Type validatorType, Type validationObjectType, Func<IServiceProvider, ActionType?> getActionType) | ||
{ | ||
List<Type> registrationInterfaces = | ||
[ | ||
typeof(IValidator<>).MakeGenericType(validationObjectType), | ||
typeof(IActionValidator<>).MakeGenericType(validationObjectType) | ||
]; | ||
|
||
foreach (var registrationInterface in registrationInterfaces) | ||
{ | ||
services.AddScoped(registrationInterface, x => | ||
{ | ||
var factory = x.GetRequiredService<IActionValidatorFactory>(); | ||
var validator = factory.GetValidatorInternal(validatorType, getActionType: getActionType); | ||
|
||
return validator; | ||
}); | ||
|
||
ActionValidatorFactory.ValidatorTypeMap[registrationInterface] = validatorType; | ||
} | ||
|
||
return services; | ||
} | ||
} |
96 changes: 0 additions & 96 deletions
96
...Validation/BitzArt.FluentValidation.Extensions/Extensions/AddActionValidatorsExtension.cs
This file was deleted.
Oops, something went wrong.
7 changes: 6 additions & 1 deletion
7
src/FluentValidation/BitzArt.FluentValidation.Extensions/Interfaces/IActionValidator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,11 @@ | ||
namespace FluentValidation; | ||
|
||
public interface IActionValidator<T> : IValidator<T>, IActionValidator | ||
{ | ||
|
||
} | ||
|
||
public interface IActionValidator | ||
{ | ||
public ActionType ActionType { get; set; } | ||
public ActionType? Action { get; internal set; } | ||
} |
55 changes: 55 additions & 0 deletions
55
src/FluentValidation/BitzArt.FluentValidation.Extensions/Services/ActionValidatorFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using System.Collections.Concurrent; | ||
|
||
namespace FluentValidation; | ||
|
||
internal class ActionValidatorFactory(IServiceProvider serviceProvider) : IActionValidatorFactory | ||
{ | ||
internal static ConcurrentDictionary<Type, Type> ValidatorTypeMap = []; | ||
|
||
internal IServiceProvider _serviceProvider = serviceProvider; | ||
|
||
private ActionType? _actionType = null; | ||
|
||
public IActionValidator<T> GetValidator<T>(ActionType actionType) | ||
=> (IActionValidator<T>)GetValidatorInternal(typeof(IActionValidator<T>), definedActionType: actionType); | ||
|
||
public IActionValidator GetValidator(Type objectType, ActionType actionType) | ||
=> GetValidatorInternal(typeof(IActionValidator<>).MakeGenericType(objectType), definedActionType: actionType); | ||
|
||
public IActionValidator GetValidatorInternal(Type validatorType, Func<IServiceProvider, ActionType?>? actionTypeResolver = null, ActionType? definedActionType = null) | ||
{ | ||
bool cleanup = false; | ||
try | ||
{ | ||
var implementationType = ValidatorTypeMap[validatorType] | ||
?? throw new ArgumentException($"{validatorType.Name} is not registered as ActionValidator"); | ||
|
||
if (definedActionType.HasValue) | ||
{ | ||
_actionType = definedActionType; | ||
cleanup = true; | ||
} | ||
|
||
var validator = (IActionValidator)_serviceProvider.GetRequiredService(implementationType); | ||
|
||
if (_actionType.HasValue) | ||
{ | ||
validator.Action = _actionType!.Value; | ||
return validator; | ||
} | ||
|
||
if (actionTypeResolver is not null) | ||
{ | ||
validator.Action = actionTypeResolver(_serviceProvider); | ||
return validator; | ||
} | ||
|
||
return validator; | ||
} | ||
finally | ||
{ | ||
if (cleanup) _actionType = null; | ||
} | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
src/FluentValidation/BitzArt.FluentValidation.Extensions/Services/IActionValidatorFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
| ||
namespace FluentValidation; | ||
|
||
public interface IActionValidatorFactory | ||
{ | ||
public IActionValidator<T> GetValidator<T>(ActionType actionType); | ||
|
||
public IActionValidator GetValidator(Type objectType, ActionType actionType); | ||
|
||
internal IActionValidator GetValidatorInternal(Type validatorType, Func<IServiceProvider, ActionType?> getActionType, ActionType? actionType = null); | ||
} |
16 changes: 4 additions & 12 deletions
16
src/FluentValidation/BitzArt.FluentValidation.Extensions/Validators/ActionValidator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,12 @@ | ||
namespace FluentValidation; | ||
|
||
public abstract class ActionValidator<T> : AbstractValidator<T>, IActionValidator | ||
public abstract class ActionValidator<T> : AbstractValidator<T>, IActionValidator<T> | ||
{ | ||
private ActionType? _actionType; | ||
public ActionType ActionType | ||
{ | ||
get => _actionType is not null ? | ||
_actionType!.Value : | ||
throw new ArgumentException("ActionType is not configured for this ActionValidator."); | ||
|
||
set => _actionType = value; | ||
} | ||
public ActionType? Action { get; set; } | ||
|
||
public IConditionBuilder When(ActionType actionType, Action action) | ||
=> When(x => ActionType == actionType, action); | ||
=> When(x => Action == actionType, action); | ||
|
||
public IConditionBuilder Unless(ActionType actionType, Action action) | ||
=> Unless(x => ActionType == actionType, action); | ||
=> Unless(x => Action == actionType, action); | ||
} |
Oops, something went wrong.