private void UnregisterValidationRule(ValidationRule rule) { lock (syncRoot) { ValidationRules.Remove(rule); } }
private void RegisterValidationRule(ValidationRule rule) { lock (syncRoot) { ValidationRules.Add(rule); } }
private void SaveRuleValidationResultAndNotifyIfNeeded(ValidationRule rule, RuleResult ruleResult, SynchronizationContext syncContext) { lock (syncRoot) { IEnumerable<object> ruleTargets = rule.Target.UnwrapTargets(); foreach (object ruleTarget in ruleTargets) { IDictionary<ValidationRule, RuleResult> targetRuleMap = GetRuleMapForTarget(ruleTarget); RuleResult currentRuleResult = GetCurrentValidationResultForRule(targetRuleMap, rule); if (!Equals(currentRuleResult, ruleResult)) { lock (ruleValidationResultMap) { targetRuleMap[rule] = ruleResult; } // Notify that validation result for the target has changed NotifyResultChanged(ruleTarget, GetResult(ruleTarget), syncContext); } } } }
private IAsyncValidationRule AddRuleCore(IValidationTarget target, Func<RuleResult> validateDelegate, Func<Task<RuleResult>> asyncValidateAction) { var rule = new ValidationRule(target, validateDelegate, asyncValidateAction); RegisterValidationRule(rule); return rule; }
private RuleResult ExecuteRuleCore(ValidationRule rule) { RuleResult result = RuleResult.Valid(); if (!rule.SupportsSyncValidation) { var completedEvent = new ManualResetEvent(false); rule.EvaluateAsync().ContinueWith(t => { result = t.Result; completedEvent.Set(); }); var isCompleted = completedEvent.WaitOne(AsyncRuleExecutionTimeout); if (!isCompleted) { throw new TimeoutException("Rule validation did not complete in specified timeout."); } } else { result = rule.Evaluate(); } return result; }
private static RuleResult GetCurrentValidationResultForRule( IDictionary<ValidationRule, RuleResult> ruleMap, ValidationRule rule) { lock (ruleMap) { if (!ruleMap.ContainsKey(rule)) { ruleMap.Add(rule, RuleResult.Valid()); } return ruleMap[rule]; } }
private static void AddErrorsFromRuleResult(ValidationResult resultToAddTo, ValidationRule validationRule, RuleResult ruleResult) { if (!ruleResult.IsValid) { IEnumerable<object> errorTargets = validationRule.Target.UnwrapTargets(); foreach (object errorTarget in errorTargets) { foreach (string ruleError in ruleResult.Errors) { resultToAddTo.AddError(errorTarget, ruleError); } } } }
private bool ShouldExecuteOnAlreadyInvalidTarget(ValidationRule rule) { var defaultValue = Settings.DefaultRuleSettings?.ExecuteOnAlreadyInvalidTarget ?? false; return rule.Settings.ExecuteOnAlreadyInvalidTarget.GetValueOrDefault(defaultValue); }
private async Task<bool> ExecuteRuleAsync(ValidationRule rule, ISet<object> failedTargets, ValidationResult validationResultAccumulator, SynchronizationContext syncContext) { // Skip rule if the target is already invalid and the rule is not configured to execute anyway if (failedTargets.Contains(rule.Target) && !ShouldExecuteOnAlreadyInvalidTarget(rule)) { // Assume that the rule is valid at this point because we are not interested in this error until // previous rule is fixed. SaveRuleValidationResultAndNotifyIfNeeded(rule, RuleResult.Valid(), syncContext); return true; } var ruleResult = !rule.SupportsSyncValidation ? await rule.EvaluateAsync().ConfigureAwait(false) : rule.Evaluate(); SaveRuleValidationResultAndNotifyIfNeeded(rule, ruleResult, syncContext); AddErrorsFromRuleResult(validationResultAccumulator, rule, ruleResult); if (!ruleResult.IsValid) { failedTargets.Add(rule.Target); } return true; }
private static Task<RuleResult> ExecuteRuleCoreAsync(ValidationRule rule) { Task<RuleResult> resultTask; if (!rule.SupportsSyncValidation) { resultTask = rule.EvaluateAsync(); } else { var tcs = new TaskCompletionSource<RuleResult>(); var result = rule.Evaluate(); tcs.SetResult(result); resultTask = tcs.Task; } return resultTask; }