コード例 #1
0
        /// <summary>
        /// Defines a condition that applies to several rules
        /// </summary>
        /// <param name="predicate">The condition that should apply to multiple rules</param>
        /// <param name="action">Action that encapsulates the rules.</param>
        /// <returns></returns>
        public IConditionBuilder When(Func <T, bool> predicate, Action action)
        {
            var propertyRules = new List <IValidationRule>();

            using (_rules.OnItemAdded(propertyRules.Add)) {
                action();
            }

            // Generate unique ID for this shared condition.
            var id = "_FV_Condition_" + Guid.NewGuid();

            bool Condition(ValidationContext context)
            {
                string cacheId = null;

                if (context.InstanceToValidate != null)
                {
                    cacheId = id + context.InstanceToValidate.GetHashCode();

                    if (context.RootContextData.TryGetValue(cacheId, out var value))
                    {
                        if (value is bool result)
                        {
                            return(result);
                        }
                    }
                }

                var executionResult = predicate((T)context.InstanceToValidate);

                if (context.InstanceToValidate != null)
                {
                    context.RootContextData[cacheId] = executionResult;
                }
                return(executionResult);
            }

            // Must apply the predicate after the rule has been fully created to ensure any rules-specific conditions have already been applied.
            foreach (var rule in propertyRules)
            {
                //TODO for FV 9 remove explicit reference to CollectionPropertyRule.
                if (rule is PropertyRule p)
                {
                    p.ApplySharedCondition(Condition);
                }
                else
                {
                    throw new NotSupportedException("Cannot call the root-level When/Unless methods on rules that don't inherit from PropertyRule");
                }
            }

            return(new ConditionOtherwiseBuilder(_rules, Condition));
        }
コード例 #2
0
        /// <summary>
        /// Defines a condition that applies to several rules
        /// </summary>
        /// <param name="predicate">The condition that should apply to multiple rules</param>
        /// <param name="action">Action that encapsulates the rules.</param>
        /// <returns></returns>
        public IConditionBuilder When(Func <T, ValidationContext <T>, bool> predicate, Action action)
        {
            var propertyRules = new List <IValidationRuleInternal <T> >();

            using (_rules.OnItemAdded(propertyRules.Add)) {
                action();
            }

            // Generate unique ID for this shared condition.
            var id = "_FV_Condition_" + Guid.NewGuid();

            bool Condition(IValidationContext context)
            {
                var actualContext = ValidationContext <T> .GetFromNonGenericContext(context);

                if (actualContext.InstanceToValidate != null)
                {
                    if (actualContext.SharedConditionCache.TryGetValue(id, out var cachedResults))
                    {
                        if (cachedResults.TryGetValue(actualContext.InstanceToValidate, out bool result))
                        {
                            return(result);
                        }
                    }
                }

                var executionResult = predicate(actualContext.InstanceToValidate, actualContext);

                if (actualContext.InstanceToValidate != null)
                {
                    if (actualContext.SharedConditionCache.TryGetValue(id, out var cachedResults))
                    {
                        cachedResults.Add(actualContext.InstanceToValidate, executionResult);
                    }
                    else
                    {
                        actualContext.SharedConditionCache.Add(id, new Dictionary <T, bool> {
                            { actualContext.InstanceToValidate, executionResult }
                        });
                    }
                }
                return(executionResult);
            }

            // Must apply the predicate after the rule has been fully created to ensure any rules-specific conditions have already been applied.
            foreach (var rule in propertyRules)
            {
                rule.ApplySharedCondition(Condition);
            }

            return(new ConditionOtherwiseBuilder <T>(_rules, Condition));
        }
コード例 #3
0
        /// <summary>
        /// Defines an asynchronous condition that applies to several rules
        /// </summary>
        /// <param name="predicate">The asynchronous condition that should apply to multiple rules</param>
        /// <param name="action">Action that encapsulates the rules.</param>
        /// <returns></returns>
        public IConditionBuilder WhenAsync(Func <T, CancellationToken, Task <bool> > predicate, Action action)
        {
            var propertyRules = new List <IValidationRule>();

            using (_rules.OnItemAdded(propertyRules.Add)) {
                action();
            }

            // Generate unique ID for this shared condition.
            var id = "_FV_AsyncCondition_" + Guid.NewGuid();

            async Task <bool> Condition(ValidationContext context, CancellationToken ct)
            {
                string cacheId = null;

                if (context.InstanceToValidate != null)
                {
                    cacheId = id + context.InstanceToValidate.GetHashCode();

                    if (context.RootContextData.TryGetValue(cacheId, out var value))
                    {
                        if (value is bool result)
                        {
                            return(result);
                        }
                    }
                }

                var executionResult = await predicate((T)context.InstanceToValidate, ct);

                if (context.InstanceToValidate != null)
                {
                    context.RootContextData[cacheId] = executionResult;
                }
                return(executionResult);
            }

            foreach (var rule in propertyRules)
            {
                //TODO for FV 9 remove explicit reference to CollectionPropertyRule.
                if (rule is PropertyRule p)
                {
                    p.ApplySharedAsyncCondition(Condition);
                }
                else
                {
                    throw new NotSupportedException("Cannot call the root-level When/Unless methods on rules that don't inherit from PropertyRule");
                }
            }

            return(new AsyncConditionOtherwiseBuilder(_rules, Condition));
        }
コード例 #4
0
        /// <summary>
        /// Defines an asynchronous condition that applies to several rules
        /// </summary>
        /// <param name="predicate">The asynchronous condition that should apply to multiple rules</param>
        /// <param name="action">Action that encapsulates the rules.</param>
        /// <returns></returns>
        public IConditionBuilder WhenAsync(Func <T, ValidationContext <T>, CancellationToken, Task <bool> > predicate, Action action)
        {
            var propertyRules = new List <IValidationRuleInternal <T> >();

            using (_rules.OnItemAdded(propertyRules.Add)) {
                action();
            }

            // Generate unique ID for this shared condition.
            var id = "_FV_AsyncCondition_" + Guid.NewGuid();

            async Task <bool> Condition(IValidationContext context, CancellationToken ct)
            {
                var actualContext = ValidationContext <T> .GetFromNonGenericContext(context);

                if (actualContext.InstanceToValidate != null)
                {
                    if (actualContext.SharedConditionCache.TryGetValue(id, out var cachedResults))
                    {
                        if (cachedResults.TryGetValue(actualContext.InstanceToValidate, out bool result))
                        {
                            return(result);
                        }
                    }
                }

                var executionResult = await predicate((T)context.InstanceToValidate, ValidationContext <T> .GetFromNonGenericContext(context), ct);

                if (actualContext.InstanceToValidate != null)
                {
                    if (actualContext.SharedConditionCache.TryGetValue(id, out var cachedResults))
                    {
                        cachedResults.Add(actualContext.InstanceToValidate, executionResult);
                    }
                    else
                    {
                        actualContext.SharedConditionCache.Add(id, new Dictionary <T, bool> {
                            { actualContext.InstanceToValidate, executionResult }
                        });
                    }
                }
                return(executionResult);
            }

            foreach (var rule in propertyRules)
            {
                rule.ApplySharedAsyncCondition(Condition);
            }

            return(new AsyncConditionOtherwiseBuilder <T>(_rules, Condition));
        }
コード例 #5
0
        public virtual void Otherwise(Action action)
        {
            var propertyRules = new List <IValidationRule>();

            Action <IValidationRule> onRuleAdded = propertyRules.Add;

            using (_rules.OnItemAdded(onRuleAdded)) {
                action();
            }

            foreach (var rule in propertyRules)
            {
                rule.ApplySharedAsyncCondition(async(ctx, ct) => !await _condition(ctx, ct));
            }
        }
コード例 #6
0
        public virtual void Otherwise(Action action)
        {
            var propertyRules = new List <IValidationRuleInternal <T> >();

            Action <IValidationRuleInternal <T> > onRuleAdded = propertyRules.Add;

            using (_rules.OnItemAdded(onRuleAdded)) {
                action();
            }

            foreach (var rule in propertyRules)
            {
                rule.ApplySharedCondition(ctx => !_condition(ctx));
            }
        }
コード例 #7
0
        /// <summary>
        /// Defines a condition that applies to several rules
        /// </summary>
        /// <param name="predicate">The condition that should apply to multiple rules</param>
        /// <param name="action">Action that encapsulates the rules.</param>
        /// <returns></returns>
        public IConditionBuilder When(Func <T, ValidationContext <T>, bool> predicate, Action action)
        {
            var propertyRules = new List <IValidationRule>();

            using (_rules.OnItemAdded(propertyRules.Add)) {
                action();
            }

            // Generate unique ID for this shared condition.
            var id = "_FV_Condition_" + Guid.NewGuid();

            bool Condition(IValidationContext context)
            {
                string cacheId = null;

                if (context.InstanceToValidate != null)
                {
                    cacheId = id + context.InstanceToValidate.GetHashCode();

                    if (context.RootContextData.TryGetValue(cacheId, out var value))
                    {
                        if (value is bool result)
                        {
                            return(result);
                        }
                    }
                }

                var executionResult = predicate((T)context.InstanceToValidate, ValidationContext <T> .GetFromNonGenericContext(context));

                if (context.InstanceToValidate != null)
                {
                    context.RootContextData[cacheId] = executionResult;
                }
                return(executionResult);
            }

            // Must apply the predicate after the rule has been fully created to ensure any rules-specific conditions have already been applied.
            foreach (var rule in propertyRules)
            {
                rule.ApplySharedCondition(Condition);
            }

            return(new ConditionOtherwiseBuilder(_rules, Condition));
        }
コード例 #8
0
        /// <summary>
        /// Defines an asynchronous condition that applies to several rules
        /// </summary>
        /// <param name="predicate">The asynchronous condition that should apply to multiple rules</param>
        /// <param name="action">Action that encapsulates the rules.</param>
        /// <returns></returns>
        public IConditionBuilder WhenAsync(Func <T, ValidationContext <T>, CancellationToken, Task <bool> > predicate, Action action)
        {
            var propertyRules = new List <IValidationRule>();

            using (_rules.OnItemAdded(propertyRules.Add)) {
                action();
            }

            // Generate unique ID for this shared condition.
            var id = "_FV_AsyncCondition_" + Guid.NewGuid();

            async Task <bool> Condition(IValidationContext context, CancellationToken ct)
            {
                string cacheId = null;

                if (context.InstanceToValidate != null)
                {
                    cacheId = id + context.InstanceToValidate.GetHashCode();

                    if (context.RootContextData.TryGetValue(cacheId, out var value))
                    {
                        if (value is bool result)
                        {
                            return(result);
                        }
                    }
                }

                var executionResult = await predicate((T)context.InstanceToValidate, ValidationContext <T> .GetFromNonGenericContext(context), ct);

                if (context.InstanceToValidate != null)
                {
                    context.RootContextData[cacheId] = executionResult;
                }
                return(executionResult);
            }

            foreach (var rule in propertyRules)
            {
                rule.ApplySharedAsyncCondition(Condition);
            }

            return(new AsyncConditionOtherwiseBuilder(_rules, Condition));
        }
コード例 #9
0
        public virtual void Otherwise(Action action)
        {
            var propertyRules = new List <IValidationRule>();

            Action <IValidationRule> onRuleAdded = propertyRules.Add;

            using (_rules.OnItemAdded(onRuleAdded)) {
                action();
            }

            foreach (var rule in propertyRules)
            {
                if (rule is PropertyRule p)
                {
                    p.ApplySharedAsyncCondition(async(ctx, ct) => !await _condition(ctx, ct));
                }
                else
                {
                    throw new NotSupportedException("Cannot call the root-level When/Unless methods on rules that don't inherit from PropertyRule");
                }
            }
        }
コード例 #10
0
        /// <summary>
        /// Defines a condition that applies to several rules
        /// </summary>
        /// <param name="predicate">The condition that should apply to multiple rules</param>
        /// <param name="action">Action that encapsulates the rules.</param>
        /// <returns></returns>
        public IConditionBuilder When(Func <T, bool> predicate, Action action)
        {
            var propertyRules = new List <IValidationRule>();

            Action <IValidationRule> onRuleAdded = propertyRules.Add;

            using (_rules.OnItemAdded(onRuleAdded)) {
                action();
            }

            // Generate unique ID for this shared condition.
            var id = "_FV_Condition_" + Guid.NewGuid();

            bool Condition(PropertyValidatorContext context)
            {
                if (context.ParentContext.RootContextData.TryGetValue(id, out var value))
                {
                    if (value is bool result)
                    {
                        return(result);
                    }
                }

                var executionResult = predicate((T)context.Instance);

                context.ParentContext.RootContextData[id] = executionResult;
                return(executionResult);
            }

            // Must apply the predicate after the rule has been fully created to ensure any rules-specific conditions have already been applied.
            foreach (var rule in propertyRules)
            {
                rule.ApplyCondition(Condition);
            }

            return(new ConditionOtherwiseBuilder(_rules, Condition));
        }
コード例 #11
0
        /// <summary>
        /// Defines an asynchronous condition that applies to several rules
        /// </summary>
        /// <param name="predicate">The asynchronous condition that should apply to multiple rules</param>
        /// <param name="action">Action that encapsulates the rules.</param>
        /// <returns></returns>
        public IConditionBuilder WhenAsync(Func <T, CancellationToken, Task <bool> > predicate, Action action)
        {
            var propertyRules = new List <IValidationRule>();

            Action <IValidationRule> onRuleAdded = propertyRules.Add;

            using (_rules.OnItemAdded(onRuleAdded)) {
                action();
            }

            // Generate unique ID for this shared condition.
            var id = "_FV_AsyncCondition_" + Guid.NewGuid();

            async Task <bool> Condition(PropertyValidatorContext context, CancellationToken ct)
            {
                if (context.ParentContext.RootContextData.TryGetValue(id, out var value))
                {
                    if (value is bool result)
                    {
                        return(result);
                    }
                }

                var executionResult = await predicate((T)context.Instance, ct);

                context.ParentContext.RootContextData[id] = executionResult;
                return(executionResult);
            }

            foreach (var rule in propertyRules)
            {
                rule.ApplyAsyncCondition(Condition);
            }

            return(new AsyncConditionOtherwiseBuilder(_rules, Condition));
        }