@@ -68,175 +68,37 @@ private void RemoveEditContextDataAnnotationsValidation()
6868 CurrentEditContext . OnFieldChanged -= OnFieldChanged ;
6969 }
7070
71- #if NET11_0_OR_GREATER
7271 internal Task < bool > ValidateAsync ( CancellationToken cancellationToken = default ) => CurrentEditContext . ValidateAsync ( cancellationToken ) ;
7372
7473 private void OnValidationRequested ( object ? sender , ValidationRequestedEventArgs args )
7574 {
76- args . AddAsyncValidator ( cancellationToken => ValidateModelAsync ( CurrentEditContext , _message , Provider , cancellationToken ) ) ;
75+ args . AddAsyncValidator ( ValidateModelAsync ) ;
7776 }
7877
7978 private void OnFieldChanged ( object ? sender , FieldChangedEventArgs args )
8079 {
8180 var fieldIdentifier = args . FieldIdentifier ;
8281 CurrentEditContext . RegisterAsyncFieldValidator ( fieldIdentifier , cancellationToken => ValidateFieldAsync ( CurrentEditContext , _message , fieldIdentifier , Provider , cancellationToken ) ) ;
8382 }
84- #else
85- #if NET9_0_OR_GREATER
86- private readonly Lock _fieldValidationLock = new ( ) ;
87- #else
88- private readonly object _fieldValidationLock = new ( ) ;
89- #endif
90-
91- private readonly SemaphoreSlim _validationLock = new ( 1 , 1 ) ;
92- private readonly Dictionary < FieldIdentifier , FieldValidationOperation > _fieldValidationOperations = [ ] ;
93- private bool _suppressValidationRequested ;
9483
95- internal async Task < bool > ValidateAsync ( CancellationToken cancellationToken = default )
84+ private async Task ValidateModelAsync ( CancellationToken cancellationToken )
9685 {
97- await _validationLock . WaitAsync ( cancellationToken ) ;
9886 try
9987 {
100- CancelFieldValidations ( ) ;
101- _message . Clear ( ) ;
102-
103- bool synchronousValid ;
104- _suppressValidationRequested = true ;
105- try
106- {
107- // NET10 只有同步方法
108- synchronousValid = CurrentEditContext . Validate ( ) ;
109- }
110- finally
111- {
112- _suppressValidationRequested = false ;
113- }
114-
115- // 通过 _suppressValidationRequested 控制 OnValidationRequested 事件中的 ValidateModelAsync 不被调用,避免重复验证
116- var valid = await ValidateModelAsync ( CurrentEditContext , _message , Provider , cancellationToken ) ;
117- return synchronousValid && valid && ! CurrentEditContext . GetValidationMessages ( ) . Any ( ) ;
88+ await ValidateModelAsync ( CurrentEditContext , _message , Provider , cancellationToken ) ;
11889 }
119- catch ( OperationCanceledException )
90+ catch ( OperationCanceledException ) when ( cancellationToken . IsCancellationRequested )
12091 {
12192 throw ;
12293 }
12394 catch ( Exception exception )
12495 {
12596 Logger . LogError ( exception , "An exception occurred while validating the form." ) ;
126- return false ;
127- }
128- finally
129- {
130- _validationLock . Release ( ) ;
131- }
132- }
133-
134- private async void OnValidationRequested ( object ? sender , ValidationRequestedEventArgs args )
135- {
136- if ( ! _suppressValidationRequested )
137- {
138- try
139- {
140- await ValidateModelAsync ( CurrentEditContext , _message , Provider , CancellationToken . None ) ;
141- }
142- catch ( Exception exception )
143- {
144- Logger . LogError ( exception , "An exception occurred while validating the form." ) ;
145- }
146- }
147- }
148-
149- private void OnFieldChanged ( object ? sender , FieldChangedEventArgs args )
150- {
151- var fieldIdentifier = args . FieldIdentifier ;
152-
153- FieldValidationOperation ? previousOperation ;
154- FieldValidationOperation operation ;
155- lock ( _fieldValidationLock )
156- {
157- _fieldValidationOperations . Remove ( fieldIdentifier , out previousOperation ) ;
158- operation = new FieldValidationOperation ( ) ;
159- _fieldValidationOperations . Add ( fieldIdentifier , operation ) ;
160- }
161- previousOperation ? . Cancel ( ) ;
162- _ = ValidateFieldAndCleanupAsync ( fieldIdentifier , operation ) ;
163- }
164-
165- private async Task ValidateFieldAndCleanupAsync ( FieldIdentifier fieldIdentifier , FieldValidationOperation operation )
166- {
167- try
168- {
169- await ValidateFieldAsync ( CurrentEditContext , _message , fieldIdentifier , Provider , operation . Token ) ;
170- }
171- catch ( OperationCanceledException ) when ( operation . IsCancellationRequested )
172- {
173- }
174- finally
175- {
176- lock ( _fieldValidationLock )
177- {
178- if ( _fieldValidationOperations . TryGetValue ( fieldIdentifier , out var currentOperation )
179- && ReferenceEquals ( currentOperation , operation ) )
180- {
181- _fieldValidationOperations . Remove ( fieldIdentifier ) ;
182- }
183- }
184- operation . Complete ( ) ;
185- }
186- }
187-
188- private void CancelFieldValidations ( )
189- {
190- FieldValidationOperation [ ] operations ;
191- lock ( _fieldValidationLock )
192- {
193- operations = [ .. _fieldValidationOperations . Values ] ;
194- _fieldValidationOperations . Clear ( ) ;
195- }
196- foreach ( var operation in operations )
197- {
198- operation . Cancel ( ) ;
199- }
200- }
201-
202- private sealed class FieldValidationOperation
203- {
204- private CancellationTokenSource ? _tokenSource ;
205-
206- public CancellationToken Token { get ; }
207-
208- public bool IsCancellationRequested => Token . IsCancellationRequested ;
209-
210- public FieldValidationOperation ( )
211- {
212- _tokenSource = new ( ) ;
213- Token = _tokenSource . Token ;
214- }
215-
216- public void Cancel ( )
217- {
218- var tokenSource = Interlocked . Exchange ( ref _tokenSource , null ) ;
219- if ( tokenSource != null )
220- {
221- try
222- {
223- tokenSource . Cancel ( ) ;
224- }
225- finally
226- {
227- tokenSource . Dispose ( ) ;
228- }
229- }
230- }
231-
232- public void Complete ( )
233- {
234- Interlocked . Exchange ( ref _tokenSource , null ) ? . Dispose ( ) ;
97+ throw ;
23598 }
23699 }
237- #endif
238100
239- private async Task < bool > ValidateModelAsync ( EditContext editContext , ValidationMessageStore messages , IServiceProvider provider , CancellationToken cancellationToken )
101+ private async Task ValidateModelAsync ( EditContext editContext , ValidationMessageStore messages , IServiceProvider provider , CancellationToken cancellationToken )
240102 {
241103 cancellationToken . ThrowIfCancellationRequested ( ) ;
242104 var validationContext = new ValidationContext ( editContext . Model , provider , null ) ;
@@ -265,7 +127,6 @@ private async Task<bool> ValidateModelAsync(EditContext editContext, ValidationM
265127 }
266128 }
267129 editContext . NotifyValidationStateChanged ( ) ;
268- return validationResults . Count == 0 ;
269130 }
270131
271132 private async Task ValidateFieldAsync ( EditContext editContext , ValidationMessageStore messages , FieldIdentifier field , IServiceProvider provider , CancellationToken cancellationToken )
@@ -290,9 +151,13 @@ private async Task ValidateFieldAsync(EditContext editContext, ValidationMessage
290151 {
291152 return ;
292153 }
154+ catch ( Exception exception )
155+ {
156+ Logger . LogError ( exception , "An exception occurred while validating the field." ) ;
157+ throw ;
158+ }
293159
294160 messages . Add ( field , validationResults . Where ( v => ! string . IsNullOrEmpty ( v . ErrorMessage ) ) . Select ( result => result . ErrorMessage ! ) ) ;
295-
296161 editContext . NotifyValidationStateChanged ( ) ;
297162 }
298163
@@ -301,7 +166,7 @@ private void Dispose(bool disposing)
301166 if ( disposing )
302167 {
303168#if ! NET11_0_OR_GREATER
304- CancelFieldValidations ( ) ;
169+ CurrentEditContext . CancelAsyncFieldValidations ( ) ;
305170#endif
306171 RemoveEditContextDataAnnotationsValidation ( ) ;
307172 }
0 commit comments