Exemple #1
0
        private TypedValue CreateArray(ExpressionState state)
        {
            // First child gives us the array type which will either be a primitive or reference type
            var intendedArrayType = GetChild(0).GetValue(state);

            if (intendedArrayType is not string)
            {
                throw new SpelEvaluationException(
                          GetChild(0).StartPosition,
                          SpelMessage.TYPE_NAME_EXPECTED_FOR_ARRAY_CONSTRUCTION,
                          FormatHelper.FormatClassNameForMessage(intendedArrayType?.GetType()));
            }

            var  type = (string)intendedArrayType;
            Type componentType;
            var  arrayTypeCode = SpelTypeCode.ForName(type);

            if (arrayTypeCode == SpelTypeCode.OBJECT)
            {
                componentType = state.FindType(type);
            }
            else
            {
                componentType = arrayTypeCode.Type;
            }

            object newArray;

            if (!HasInitializer)
            {
                // Confirm all dimensions were specified (for example [3][][5] is missing the 2nd dimension)
                if (_dimensions != null)
                {
                    foreach (var dimension in _dimensions)
                    {
                        if (dimension == null)
                        {
                            throw new SpelEvaluationException(StartPosition, SpelMessage.MISSING_ARRAY_DIMENSION);
                        }
                    }
                }
                else
                {
                    throw new SpelEvaluationException(StartPosition, SpelMessage.MISSING_ARRAY_DIMENSION);
                }

                var typeConverter = state.EvaluationContext.TypeConverter;

                // Shortcut for 1 dimensional
                if (_dimensions.Length == 1)
                {
                    var o         = _dimensions[0].GetTypedValue(state);
                    var arraySize = ExpressionUtils.ToInt(typeConverter, o);
                    newArray = Array.CreateInstance(componentType, arraySize);
                }
                else
                {
                    // Multi-dimensional - hold onto your hat!
                    var dims = new int[_dimensions.Length];
                    for (var d = 0; d < _dimensions.Length; d++)
                    {
                        var o = _dimensions[d].GetTypedValue(state);
                        dims[d] = ExpressionUtils.ToInt(typeConverter, o);
                    }

                    newArray = Array.CreateInstance(componentType, dims);
                }
            }
            else
            {
                // There is an initializer
                if (_dimensions == null || _dimensions.Length > 1)
                {
                    // There is an initializer but this is a multi-dimensional array (e.g. new int[][]{{1,2},{3,4}}) - this
                    // is not currently supported
                    throw new SpelEvaluationException(StartPosition, SpelMessage.MULTIDIM_ARRAY_INITIALIZER_NOT_SUPPORTED);
                }

                var typeConverter = state.EvaluationContext.TypeConverter;
                var initializer   = (InlineList)GetChild(1);

                // If a dimension was specified, check it matches the initializer length
                if (_dimensions[0] != null)
                {
                    var dValue = _dimensions[0].GetTypedValue(state);
                    var i      = ExpressionUtils.ToInt(typeConverter, dValue);
                    if (i != initializer.ChildCount)
                    {
                        throw new SpelEvaluationException(StartPosition, SpelMessage.INITIALIZER_LENGTH_INCORRECT);
                    }
                }

                // Build the array and populate it
                var arraySize = initializer.ChildCount;
                newArray = Array.CreateInstance(componentType, arraySize);
                if (arrayTypeCode == SpelTypeCode.OBJECT)
                {
                    PopulateReferenceTypeArray(state, newArray, typeConverter, initializer, componentType);
                }
                else if (arrayTypeCode == SpelTypeCode.BOOLEAN)
                {
                    PopulateBooleanArray(state, newArray, typeConverter, initializer);
                }
                else if (arrayTypeCode == SpelTypeCode.BYTE)
                {
                    PopulateByteArray(state, newArray, typeConverter, initializer);
                }
                else if (arrayTypeCode == SpelTypeCode.SBYTE)
                {
                    PopulateSByteArray(state, newArray, typeConverter, initializer);
                }
                else if (arrayTypeCode == SpelTypeCode.CHAR)
                {
                    PopulateCharArray(state, newArray, typeConverter, initializer);
                }
                else if (arrayTypeCode == SpelTypeCode.DOUBLE)
                {
                    PopulateDoubleArray(state, newArray, typeConverter, initializer);
                }
                else if (arrayTypeCode == SpelTypeCode.FLOAT)
                {
                    PopulateFloatArray(state, newArray, typeConverter, initializer);
                }
                else if (arrayTypeCode == SpelTypeCode.INT)
                {
                    PopulateIntArray(state, newArray, typeConverter, initializer);
                }
                else if (arrayTypeCode == SpelTypeCode.UINT)
                {
                    PopulateUIntArray(state, newArray, typeConverter, initializer);
                }
                else if (arrayTypeCode == SpelTypeCode.LONG)
                {
                    PopulateLongArray(state, newArray, typeConverter, initializer);
                }
                else if (arrayTypeCode == SpelTypeCode.ULONG)
                {
                    PopulateULongArray(state, newArray, typeConverter, initializer);
                }
                else if (arrayTypeCode == SpelTypeCode.SHORT)
                {
                    PopulateShortArray(state, newArray, typeConverter, initializer);
                }
                else if (arrayTypeCode == SpelTypeCode.USHORT)
                {
                    PopulateUShortArray(state, newArray, typeConverter, initializer);
                }
                else
                {
                    throw new InvalidOperationException(arrayTypeCode.Name);
                }
            }

            return(new TypedValue(newArray));
        }
Exemple #2
0
        private ITypedValue CreateNewInstance(ExpressionState state)
        {
            var arguments     = new object[ChildCount - 1];
            var argumentTypes = new List <Type>(ChildCount - 1);

            for (var i = 0; i < arguments.Length; i++)
            {
                var childValue = _children[i + 1].GetValueInternal(state);
                var value      = childValue.Value;
                arguments[i] = value;
                var valueType = value?.GetType();
                argumentTypes.Add(valueType);
            }

            var executorToUse = _cachedExecutor;

            if (executorToUse != null)
            {
                try
                {
                    return(executorToUse.Execute(state.EvaluationContext, arguments));
                }
                catch (AccessException ex)
                {
                    // Two reasons this can occur:
                    // 1. the method invoked actually threw a real exception
                    // 2. the method invoked was not passed the arguments it expected and has become 'stale'

                    // In the first case we should not retry, in the second case we should see if there is a
                    // better suited method.

                    // To determine which situation it is, the AccessException will contain a cause.
                    // If the cause is an InvocationTargetException, a user exception was thrown inside the constructor.
                    // Otherwise the constructor could not be invoked.
                    if (ex.InnerException is TargetInvocationException)
                    {
                        // User exception was the root cause - exit now
                        var rootCause = ex.InnerException.InnerException;
                        if (rootCause is SystemException)
                        {
                            throw rootCause;
                        }

                        var name = (string)_children[0].GetValueInternal(state).Value;
                        throw new SpelEvaluationException(
                                  StartPosition,
                                  rootCause,
                                  SpelMessage.CONSTRUCTOR_INVOCATION_PROBLEM,
                                  name,
                                  FormatHelper.FormatMethodForMessage(string.Empty, argumentTypes));
                    }

                    // At this point we know it wasn't a user problem so worth a retry if a better candidate can be found
                    _cachedExecutor = null;
                }
            }

            // Either there was no accessor or it no longer exists
            var typeName = (string)_children[0].GetValueInternal(state).Value;

            if (typeName == null)
            {
                throw new InvalidOperationException("No type name");
            }

            executorToUse = FindExecutorForConstructor(typeName, argumentTypes, state);
            try
            {
                _cachedExecutor = executorToUse;
                if (executorToUse is ReflectiveConstructorExecutor executor)
                {
                    _exitTypeDescriptor = CodeFlow.ToDescriptor(executor.Constructor.DeclaringType);
                }

                return(executorToUse.Execute(state.EvaluationContext, arguments));
            }
            catch (AccessException ex)
            {
                throw new SpelEvaluationException(
                          StartPosition,
                          ex,
                          SpelMessage.CONSTRUCTOR_INVOCATION_PROBLEM,
                          typeName,
                          FormatHelper.FormatMethodForMessage(string.Empty, argumentTypes));
            }
        }
Exemple #3
0
        private void WriteProperty(ITypedValue contextObject, IEvaluationContext evalContext, string name, object newValue)
        {
            if (contextObject.Value == null && _nullSafe)
            {
                return;
            }

            if (contextObject.Value == null)
            {
                throw new SpelEvaluationException(StartPosition, SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE_ON_NULL, name);
            }

            var accessorToUse = _cachedWriteAccessor;

            if (accessorToUse != null)
            {
                if (evalContext.PropertyAccessors.Contains(accessorToUse))
                {
                    try
                    {
                        accessorToUse.Write(evalContext, contextObject.Value, name, newValue);
                        return;
                    }
                    catch (Exception ex)
                    {
                        // This is OK - it may have gone stale due to a class change,
                        // let's try to get a new one and call it before giving up...
                    }
                }

                _cachedWriteAccessor = null;
            }

            var accessorsToTry = GetPropertyAccessorsToTry(contextObject.Value, evalContext.PropertyAccessors);

            try
            {
                foreach (var accessor in accessorsToTry)
                {
                    if (accessor.CanWrite(evalContext, contextObject.Value, name))
                    {
                        _cachedWriteAccessor = accessor;
                        accessor.Write(evalContext, contextObject.Value, name, newValue);
                        return;
                    }
                }
            }
            catch (AccessException ex)
            {
                throw new SpelEvaluationException(StartPosition, ex, SpelMessage.EXCEPTION_DURING_PROPERTY_WRITE, name, ex.Message);
            }

            throw new SpelEvaluationException(StartPosition, SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE, name, FormatHelper.FormatClassNameForMessage(GetObjectType(contextObject.Value)));
        }
 private void ThrowIfNotNullSafe(IList <Type> argumentTypes)
 {
     if (!_nullSafe)
     {
         throw new SpelEvaluationException(StartPosition, SpelMessage.METHOD_CALL_ON_NULL_OBJECT_NOT_ALLOWED, FormatHelper.FormatMethodForMessage(_name, argumentTypes));
     }
 }
Exemple #5
0
        private ITypedValue ReadProperty(ITypedValue contextObject, IEvaluationContext evalContext, string name)
        {
            var targetObject = contextObject.Value;

            if (targetObject == null && _nullSafe)
            {
                return(TypedValue.NULL);
            }

            var accessorToUse = _cachedReadAccessor;

            if (accessorToUse != null)
            {
                if (evalContext.PropertyAccessors.Contains(accessorToUse))
                {
                    try
                    {
                        return(accessorToUse.Read(evalContext, contextObject.Value, name));
                    }
                    catch (Exception ex)
                    {
                        // This is OK - it may have gone stale due to a class change,
                        // let's try to get a new one and call it before giving up...
                    }
                }

                _cachedReadAccessor = null;
            }

            var accessorsToTry = GetPropertyAccessorsToTry(contextObject.Value, evalContext.PropertyAccessors);

            // Go through the accessors that may be able to resolve it. If they are a cacheable accessor then
            // get the accessor and use it. If they are not cacheable but report they can read the property
            // then ask them to read it
            try
            {
                foreach (var acc in accessorsToTry)
                {
                    var accessor = acc;
                    if (accessor.CanRead(evalContext, contextObject.Value, name))
                    {
                        if (accessor is ReflectivePropertyAccessor)
                        {
                            accessor = ((ReflectivePropertyAccessor)accessor).CreateOptimalAccessor(evalContext, contextObject.Value, name);
                        }

                        _cachedReadAccessor = accessor;
                        return(accessor.Read(evalContext, contextObject.Value, name));
                    }
                }
            }
            catch (Exception ex)
            {
                throw new SpelEvaluationException(ex, SpelMessage.EXCEPTION_DURING_PROPERTY_READ, name, ex.Message);
            }

            if (contextObject.Value == null)
            {
                throw new SpelEvaluationException(SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL, name);
            }
            else
            {
                throw new SpelEvaluationException(StartPosition, SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE, _name, FormatHelper.FormatClassNameForMessage(GetObjectType(contextObject.Value)));
            }
        }