From a815e4cf4c35b9a5eb8f1b43973a898acb6bf6ff Mon Sep 17 00:00:00 2001 From: Alexey Lobanov Date: Fri, 29 Jul 2022 15:56:30 +0300 Subject: [PATCH] Remove FluentValidation Extension There is a need to remove FluentValidation on ComponentBase disposed --- .../EditContextFluentValidationExtensions.cs | 34 ++++++++++++++++--- .../FluentValidationsValidator.cs | 23 ++++++++++++- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/Blazored.FluentValidation/EditContextFluentValidationExtensions.cs b/src/Blazored.FluentValidation/EditContextFluentValidationExtensions.cs index c06c9f4..1326292 100644 --- a/src/Blazored.FluentValidation/EditContextFluentValidationExtensions.cs +++ b/src/Blazored.FluentValidation/EditContextFluentValidationExtensions.cs @@ -1,4 +1,5 @@ -using FluentValidation; +using System.Collections.Concurrent; +using FluentValidation; using FluentValidation.Internal; using Microsoft.AspNetCore.Components.Forms; using Microsoft.Extensions.DependencyInjection; @@ -11,6 +12,8 @@ public static class EditContextFluentValidationExtensions private static readonly char[] Separators = { '.', '[' }; private static readonly List ScannedAssembly = new(); private static readonly List AssemblyScanResults = new(); + private static readonly ConcurrentDictionary> ValidationRequestedHandlers = new(); + private static readonly ConcurrentDictionary> FieldChangedHandlers = new(); public const string PendingAsyncValidation = "AsyncValidationTask"; public static void AddFluentValidation(this EditContext editContext, IServiceProvider serviceProvider, bool disableAssemblyScanning, IValidator? validator, FluentValidationValidator fluentValidationValidator) @@ -19,11 +22,32 @@ public static void AddFluentValidation(this EditContext editContext, IServicePro var messages = new ValidationMessageStore(editContext); - editContext.OnValidationRequested += - async (sender, _) => await ValidateModel((EditContext)sender!, messages, serviceProvider, disableAssemblyScanning, fluentValidationValidator, validator); + EventHandler validationRequestedHandler + = async (sender, _) => await ValidateModel((EditContext)sender!, messages, serviceProvider, disableAssemblyScanning, fluentValidationValidator, validator); + if (ValidationRequestedHandlers.TryAdd(editContext, validationRequestedHandler)) + editContext.OnValidationRequested += validationRequestedHandler; - editContext.OnFieldChanged += - async (_, eventArgs) => await ValidateField(editContext, messages, eventArgs.FieldIdentifier, serviceProvider, disableAssemblyScanning, validator); + EventHandler fieldChangedHandler + = async (_, eventArgs) => await ValidateField(editContext, messages, eventArgs.FieldIdentifier, serviceProvider, disableAssemblyScanning, validator); + if (FieldChangedHandlers.TryAdd(editContext, fieldChangedHandler)) + editContext.OnFieldChanged += fieldChangedHandler; + } + + public static void RemoveFluentValidation(this EditContext editContext) + { + ArgumentNullException.ThrowIfNull(editContext, nameof(editContext)); + + if (ValidationRequestedHandlers.TryGetValue(editContext, out var validationRequestedHandler)) + { + editContext.OnValidationRequested -= validationRequestedHandler; + ValidationRequestedHandlers.TryRemove(editContext, out _); + } + + if (FieldChangedHandlers.TryGetValue(editContext, out var fieldChangedHandler)) + { + editContext.OnFieldChanged -= fieldChangedHandler; + FieldChangedHandlers.TryRemove(editContext, out _); + } } private static async Task ValidateModel(EditContext editContext, diff --git a/src/Blazored.FluentValidation/FluentValidationsValidator.cs b/src/Blazored.FluentValidation/FluentValidationsValidator.cs index ae8e6f9..c417918 100644 --- a/src/Blazored.FluentValidation/FluentValidationsValidator.cs +++ b/src/Blazored.FluentValidation/FluentValidationsValidator.cs @@ -7,7 +7,7 @@ namespace Blazored.FluentValidation; -public class FluentValidationValidator : ComponentBase +public class FluentValidationValidator : ComponentBase, IDisposable { [Inject] private IServiceProvider ServiceProvider { get; set; } = default!; @@ -81,4 +81,25 @@ protected override void OnInitialized() CurrentEditContext.AddFluentValidation(ServiceProvider, DisableAssemblyScanning, Validator, this); } + + private bool _disposedValue; + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + CurrentEditContext?.RemoveFluentValidation(); + } + + _disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } } \ No newline at end of file