示例#1
0
        private DryvCompiledRule Translate(DryvCompiledRule rule, ITranslator translator)
        {
            if (rule.TranslatedValidationExpression != null ||
                rule.TranslationError != null)
            {
                return(rule);
            }

            try
            {
                var translatedRule = translator.Translate(rule.ValidationExpression, rule.PropertyExpression);

                rule.TranslatedValidationExpression = translatedRule.Factory;
                rule.PreevaluationOptionTypes       = translatedRule.OptionTypes;
                rule.CodeTemplate = translatedRule.CodeTemplate;
            }
            catch (DryvException ex)
            {
                switch (this.options.TranslationErrorBehavior)
                {
                case TranslationErrorBehavior.ValidateOnServer:
                    rule.TranslatedValidationExpression = null;
                    rule.PreevaluationOptionTypes       = null;
                    rule.TranslationError = ex;
                    break;

                default:
                    throw;
                }
            }

            return(rule);
        }
示例#2
0
        private string GetTranslationFromRule(DryvCompiledRule rule, object[] preevaluationOptions)
        {
            try
            {
                return(rule.TranslatedValidationExpression(this.serviceProvider, preevaluationOptions));
            }
            catch (NullReferenceException ex)
            {
                var p          = rule.ValidationExpression.Parameters;
                var parameters = preevaluationOptions.Select((o, i) => new { o, i }).Where(x => x.o == null).Select(x => $"'{p[x.i].Name}'").ToList();

                var msg = parameters.Count switch
                {
                    0 => "An error occurred while translating the validation rule.",
                    1 => $"The injected rule parameter {parameters.First()} is null.",
                    _ => $"An injected rule parameter is null. Possible candidates are {string.Join(", ", parameters)}."
                };

                throw CreateException(msg, ex, rule);
            }
            catch (Exception ex)
            {
                throw CreateException("An error occurred while translating validation rule.", ex, rule);
            }
        }
示例#3
0
 private static void EnsurePreevaluationOptionTypes(DryvCompiledRule rule)
 {
     if (rule.PreevaluationOptionTypes?.Any() != true)
     {
         rule.PreevaluationOptionTypes = (from p in rule.ValidationExpression.Parameters.Skip(1)
                                          select p.Type).ToArray();
     }
 }
示例#4
0
        public bool IsEnabled(DryvCompiledRule rule, Func <Type, object> objectFactory)
        {
            Compile(rule);

            var options = GetPreevaluationOptions(rule, objectFactory);

            return(rule.CompiledEnablingExpression(options));
        }
示例#5
0
        private static void Compile(DryvCompiledRule rule)
        {
            if (rule.CompiledValidationExpression != null)
            {
                return;
            }

            rule.CompiledValidationExpression = CompileValidationExpression(rule);
            rule.CompiledEnablingExpression   = CompileEnablingExpression(rule);
        }
示例#6
0
 private static object[] GetPreevaluationOptions(DryvCompiledRule rule, Func <Type, object> objectFactory)
 {
     foreach (var optionType in rule.PreevaluationOptionTypes)
     {
         var options = objectFactory(optionType);
         if (options == null)
         {
             throw new DryvPreevalutationResolvingException($"Could not resolve type '{optionType.FullName}' for rule pre-evaluation.");
         }
     }
     return((from t in rule.PreevaluationOptionTypes
             select objectFactory(t)).ToArray());
 }
示例#7
0
        public Task <DryvResultMessage> ValidateAsync(DryvCompiledRule rule, object model, Func <Type, object> objectFactory)
        {
            Compile(rule);

            var options = GetPreevaluationOptions(rule, objectFactory);
            var result  = rule.CompiledValidationExpression(model, options);

            switch (result)
            {
            case DryvResultMessage dryvResult: return(Task.FromResult(dryvResult));

            case Task <DryvResultMessage> task: return(task);

            default: throw new InvalidOperationException($"Compiled validation expression for property {rule.Property.DeclaringType.FullName}.{rule.Property.Name} should return '{result.GetType().FullName}'. Only DryvResultMessage and Task<DryvResultMessage> are allowed.");
            }
        }
示例#8
0
        public bool IsDisabled(DryvCompiledRule rule, object model, Func <Type, object> objectFactory)
        {
            if (rule.ValidationExpression.ReturnType != typeof(bool))
            {
                return(false);
            }

            Compile(rule);

            var options = GetPreevaluationOptions(rule, objectFactory);

            try
            {
                return((bool)rule.CompiledValidationExpression(model, options));
            }
            catch (Exception ex)
            {
                throw new DryvValidationExecutionException(rule, ex);
            }
        }
示例#9
0
        public DryvResultMessage Validate(DryvCompiledRule rule, object model, Func <Type, object> objectFactory)
        {
            if (typeof(Task).IsAssignableFrom(rule.ValidationExpression.ReturnType))
            {
                return(DryvResultMessage.Success);
            }

            Compile(rule);

            var options = GetPreevaluationOptions(rule, objectFactory);

            try
            {
                return((DryvResultMessage)rule.CompiledValidationExpression(model, options));
            }
            catch (Exception ex)
            {
                throw new DryvValidationExecutionException(rule, ex);
            }
        }
示例#10
0
        private static Func <object, object[], object> CompileValidationExpression(DryvCompiledRule rule)
        {
            var lambdaExpression = rule.ValidationExpression;

            EnsurePreevaluationOptionTypes(rule);

            var modelParameter   = Expression.Parameter(typeof(object), "model");
            var optionsParameter = Expression.Parameter(typeof(object[]), "options");
            var invokeArguments  = new List <Expression>
            {
                Expression.Convert(modelParameter, lambdaExpression.Parameters.First().Type)
            };

            AddOptionParameters(invokeArguments, lambdaExpression, optionsParameter, 1);

            var invokeExpression = Expression.Invoke(lambdaExpression, invokeArguments);
            var resultLambda     = rule.IsDisablingRule
                ? Expression.Lambda <Func <object, object[], object> >(Expression.Convert(invokeExpression, typeof(object)), modelParameter, optionsParameter)
                : Expression.Lambda <Func <object, object[], object> >(invokeExpression, modelParameter, optionsParameter);

            return(resultLambda.Compile());
        }
示例#11
0
        private static Func <object[], bool> CompileEnablingExpression(DryvCompiledRule rule)
        {
            var lambdaExpression = rule.EnablingExpression;

            EnsurePreevaluationOptionTypes(rule);

            var optionsParameter = Expression.Parameter(typeof(object[]), "options");
            Expression <Func <object[], bool> > resultLambda;

            if (lambdaExpression != null)
            {
                var invokeArguments = new List <Expression>();
                AddOptionParameters(invokeArguments, lambdaExpression, optionsParameter);
                var invokeExpression = Expression.Invoke(lambdaExpression, invokeArguments);
                resultLambda = Expression.Lambda <Func <object[], bool> >(invokeExpression, optionsParameter);
            }
            else
            {
                resultLambda = Expression.Lambda <Func <object[], bool> >(Expression.Constant(true), optionsParameter);
            }

            return(resultLambda.Compile());
        }
示例#12
0
        private static DryvTranslationException CreateException(string msg, Exception ex, DryvCompiledRule rule)
        {
            var sb = new StringBuilder(msg);

            sb.AppendLine();
            sb.Append("The error occurred while translating the following rule for property ");
            sb.Append(rule.Property.Name);
            sb.Append(" on type ");
            sb.Append(rule.ModelType.FullName);
            sb.AppendLine(":");
            sb.Append(rule.ValidationExpression);

            return(new DryvTranslationException(sb.ToString(), ex));
        }
示例#13
0
 public DryvRuleTreeNode(string path, DryvCompiledRule rule)
 {
     this.Path = path ?? throw new ArgumentNullException(nameof(path));
     this.Rule = rule ?? throw new ArgumentNullException(nameof(rule));
 }
示例#14
0
 public DryvValidationExecutionException(DryvCompiledRule rule, Exception innerException) :
     base($"An error occurred while evaluating rule for '{GetPropertyPath(rule)}: {innerException.Message}'", innerException)
 {
 }
示例#15
0
 private static string GetPropertyPath(DryvCompiledRule rule)
 {
     return(string.IsNullOrWhiteSpace(rule.ModelPath)
         ? rule.Property.Name
         : $"{rule.ModelPath}.{rule.Property.Name}");
 }