private void WriteStringLength(ILWriter writer, PropertyInfo property, StringLengthAttribute attribute)
        {
            var local = writer.DeclareLocal <string>();

            if (property.PropertyType == typeof(string))
            {
                writer.LoadFirstParameter();
                writer.GetPropertyValue(property);
                writer.SetLocal(local);

                writer.LoadLocal(local);
                writer.LoadNull();
                var notNullBlock = writer.IfEqualThen();

                var isNullMessage = CommonResults.PropertyCannotBeNull.WithValues(property.ReflectedType.Name, property.Name);
                WriteFailureResult(writer, ValidationKind.StringLength, isNullMessage);
                writer.Return();

                writer.MarkLabel(notNullBlock);

                var lengthValue = writer.DeclareLocal <int>();
                var length      = KnownMetadata.Properties.String_Length;
                writer.LoadLocal(local);
                writer.GetPropertyValue(length);
                writer.SetLocal(lengthValue);

                var minValue = attribute.Minimum;

                writer.LoadLocal(lengthValue);
                writer.LoadInt32((int)minValue);
                var longerThanMinBlock = writer.IfLessThan();

                var tooShortMessage = CommonResults.StringPropertyIsTooShort.WithValues(property.ReflectedType.Name, property.Name, minValue);
                WriteFailureResult(writer, ValidationKind.StringLength, tooShortMessage);
                writer.Return();

                writer.MarkLabel(longerThanMinBlock);

                var maxValue = attribute.Maximum;

                //The maximum value might not be set, if so then just ignore it
                if (maxValue > 0)
                {
                    writer.LoadLocal(lengthValue);
                    writer.LoadInt32((int)maxValue);
                    var shorterThanMaxBlock = writer.IfGreaterThan();

                    var tooLongMessage = CommonResults.StringPropertyIsTooLong.WithValues(property.ReflectedType.Name, property.Name, maxValue);
                    WriteFailureResult(writer, ValidationKind.StringLength, tooLongMessage);
                    writer.Return();

                    writer.MarkLabel(shorterThanMaxBlock);
                }
            }
            else
            {
                WriteNotApplicableResult(writer, ValidationKind.StringLength);
                writer.Return();
            }
        }
Beispiel #2
0
        private void WriteTryCatchBlockBody(ILWriter writer, IImmutableQueue <Type> exceptionTypes)
        {
            var currentExecutionAttempt = writer.DeclareLocal <int>();
            var shouldRetry             = writer.DeclareLocal <bool>();

            var retryLabel = writer.DefineLabel();

            writer.MarkLabel(retryLabel);

            writer.WriteIncrement(currentExecutionAttempt, 1);

            writer.TryCatch(
                endOfTryCatch =>
            {
                writer.LoadFalse();
                writer.SetLocal(shouldRetry);

                var method = KnownMetadata.Methods.IExceptionAwareAction_Do;
                writer.LoadFirstParameter();
                writer.InstanceMethodCall(method);
            },
                WriteUnrolledCatchBlocks(writer, exceptionTypes, shouldRetry, currentExecutionAttempt)
                );

            writer.LoadLocal(shouldRetry);
            var shouldNotRetry = writer.IfTrueThen();

            writer.GoTo(retryLabel);

            writer.MarkLabel(shouldNotRetry);

            writer.Return();
        }
        private void WriteCustomValidation(ILWriter writer, PropertyInfo property, CustomValidationAttribute customValidationAttribute)
        {
            var validationKind = ValidationKind.Custom;

            var validatorType = typeof(ICustomValidator <>).MakeGenericType(property.PropertyType);

            if (!customValidationAttribute.ValidatorType.CanBe(validatorType))
            {
                var message = CommonErrors.CustomValidatorMustBeOfType.WithValues(property.ReflectedType.Name, property.Name, property.PropertyType.Name);
                throw new IncorrectValidationAttributeException(typeof(CustomValidationAttribute), message);
            }

            var localValidator = writer.DeclareLocal(validatorType);

            writer.New(customValidationAttribute.ValidatorType);
            writer.SetLocal(localValidator);

            var validate = KnownMetadata.Methods.ICustomValidator_OfType(property.PropertyType);

            writer.LoadLocal(localValidator);
            writer.LoadFirstParameter();
            writer.GetPropertyValue(property);
            writer.InstanceMethodCall(validate);

            var end = writer.IfFalseThen();

            WriteFailureResult(writer, validationKind, CommonResults.CustomValidationDidNotSucceed.WithValues(property.ReflectedType.Name, property.Name));
            writer.Return();

            writer.MarkLabel(end);
        }
        private void WriteIsMatch(ILWriter writer, PropertyInfo property, IsMatchForAttribute isMatchAttribute)
        {
            var validationKind = ValidationKind.RegularExpressionMatch;
            var local          = writer.DeclareLocal <string>();

            if (property.PropertyType == typeof(string))
            {
                writer.LoadFirstParameter();
                writer.GetPropertyValue(property);
                writer.SetLocal(local);
            }
            else
            {
                var temp = writer.DeclareLocal(property.PropertyType);
                writer.LoadFirstParameter();
                writer.GetPropertyValue(property);
                writer.SetLocal(temp);

                writer.LoadLocal(temp);
                var notNull = writer.IsNotNull();

                WriteFailureResult(writer, validationKind, CommonResults.CannotValidateNullProperty.WithValues(property.ReflectedType.Name, property.Name));
                writer.Return();

                writer.MarkLabel(notNull);

                writer.LoadLocal(temp);
                writer.InstanceMethodCall(KnownMetadata.Methods.Object_ToString);
                writer.SetLocal(local);
            }

            writer.LoadLocal(local);
            writer.LoadString(isMatchAttribute.RegularExpression);
            writer.StaticMethodCall(KnownMetadata.Methods.Regex_IsMatch);
            var end = writer.IfFalseThen();

            WriteFailureResult(writer, validationKind, CommonResults.RegularExpressionWasNotMatch.WithValues(property.ReflectedType.Name, property.Name));
            writer.Return();

            writer.MarkLabel(end);
        }
Beispiel #5
0
        private IEnumerable <Action <Label> > WriteUnrolledCatchBlocks(ILWriter writer, IImmutableQueue <Type> exceptionTypes, LocalBuilder shouldRetry, LocalBuilder currentExecutionAttempt)
        {
            var handleException = KnownMetadata.Methods.IExceptionAwareAction_HandleException;

            foreach (var exceptionType in exceptionTypes)
            {
                yield return(endOfTryCatch =>
                {
                    var handleSpecificException = handleException.MakeGenericMethod(exceptionType);

                    Action catchBlockBody = () =>
                    {
                        var endOfCatch = writer.DefineLabel();
                        var localException = writer.DeclareLocal(exceptionType);
                        writer.SetLocal(localException);

                        writer.LoadFirstParameter(); //Exception-aware instance
                        writer.LoadLocal(localException);
                        writer.LoadLocal(currentExecutionAttempt);
                        writer.InstanceMethodCall(handleSpecificException);

                        //The handler refusing to handle it indicates that we should perform a retry.
                        var wasHandled = writer.IfFalseThen();

                        writer.LoadTrue();
                        writer.SetLocal(shouldRetry);
                        writer.GoTo(endOfCatch);

                        writer.MarkLabel(wasHandled);

                        writer.LoadFalse();
                        writer.SetLocal(shouldRetry);

                        writer.MarkLabel(endOfCatch);
                    };

                    writer.CatchBlock(exceptionType, endOfTryCatch, catchBlockBody);
                });
            }
        }
        private void WriteRequireNotNull(ILWriter writer, PropertyInfo property, NotNullAttribute notNullAttribute)
        {
            if (property.PropertyType.IsClass || property.PropertyType.IsInterface)
            {
                writer.LoadFirstParameter();
                writer.GetPropertyValue(property);
                writer.LoadNull();
                var elseLabel = writer.IfEqualThen();

                var message = CommonResults.PropertyCannotBeNull.WithValues(property.ReflectedType.Name, property.Name);
                WriteFailureResult(writer, ValidationKind.RequireNotNull, message);
                writer.Return();

                writer.MarkLabel(elseLabel);
            }
            else
            {
                //Value types, pointers, everything that can't be null is here
                WriteNotApplicableResult(writer, ValidationKind.RequireNotNull);
                writer.Return();
            }
        }
        void WriteValidatorBody <T>(ILWriter writer)
        {
            if (typeof(T).IsValueType)
            {
                WritePropertyValidation <T>(writer);

                WriteSuccessResult(writer);

                writer.Return();
            }
            else
            {
                writer.LoadFirstParameter(); //Load the parameter we're validating
                var isNull = writer.IsNotNull();

                WritePropertyValidation <T>(writer);

                writer.MarkLabel(isNull); //Ending mark for initial parameter null check

                WriteSuccessResult(writer);

                writer.Return();
            }
        }
        private void WriteIntegerRange(ILWriter writer, PropertyInfo property, IntegerRangeAttribute integerRangeAttribute)
        {
            var validationKind = ValidationKind.IntegerRange;

            var signedSet = new HashSet <Type>()
            {
                typeof(sbyte),
                typeof(short),
                typeof(int),
                typeof(long)
            };

            var unsignedSet = new HashSet <Type>()
            {
                typeof(byte),
                typeof(ushort),
                typeof(uint),
                typeof(ulong)
            };

            LocalBuilder local;

            if (signedSet.Contains(property.PropertyType))
            {
                local = writer.DeclareLocal <long>();
            }
            else if (unsignedSet.Contains(property.PropertyType))
            {
                local = writer.DeclareLocal <ulong>();
            }
            else
            {
                WriteNotApplicableResult(writer, validationKind);
                writer.Return();
                return;
            }

            writer.LoadFirstParameter();
            writer.GetPropertyValue(property);
            writer.Cast(property.PropertyType, local.LocalType);
            writer.SetLocal(local);

            if (integerRangeAttribute.HasMinimum && integerRangeAttribute.HasMaximum)
            {
                if (integerRangeAttribute.Minimum > integerRangeAttribute.Maximum)
                {
                    var message = CommonErrors.IntegerRangeValidationHasMinGreaterThanMax.WithValues(property.ReflectedType.Name, property.Name);
                    throw new IncorrectValidationAttributeException(typeof(IntegerRangeAttribute), message);
                }
            }

            if (integerRangeAttribute.HasMinimum)
            {
                writer.LoadLocal(local);
                writer.LoadInt64(integerRangeAttribute.Minimum);

                var isGreaterThanOrEqual = writer.IfLessThan();

                WriteFailureResult(writer, validationKind, CommonResults.IntegerPropertyIsTooLow.WithValues(property.ReflectedType.Name, property.Name, integerRangeAttribute.Minimum));
                writer.Return();

                writer.MarkLabel(isGreaterThanOrEqual);
            }

            if (integerRangeAttribute.HasMaximum)
            {
                writer.LoadLocal(local);
                writer.LoadInt64(integerRangeAttribute.Maximum);

                var isLessThanOrEqual = writer.IfGreaterThan();

                WriteFailureResult(writer, validationKind, CommonResults.IntegerPropertyIsTooHigh.WithValues(property.ReflectedType.Name, property.Name, integerRangeAttribute.Maximum));
                writer.Return();

                writer.MarkLabel(isLessThanOrEqual);
            }
        }