Exemple #1
0
        public override ITypedValue GetValueInternal(ExpressionState state)
        {
            // Possible optimization here if we cache the discovered type reference, but can we do that?
            var typeName = (string)_children[0].GetValueInternal(state).Value;

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

            if (!typeName.Contains(".") && char.IsLower(typeName[0]))
            {
                var tc = SpelTypeCode.ForName(typeName.ToUpper());
                if (tc != SpelTypeCode.OBJECT)
                {
                    // It is a primitive type
                    var atype = MakeArrayIfNecessary(tc.Type);
                    _exitTypeDescriptor = TypeDescriptor.TYPE;
                    _type = atype;
                    return(new TypedValue(atype));
                }
            }

            var clazz = state.FindType(typeName);

            clazz = MakeArrayIfNecessary(clazz);
            _exitTypeDescriptor = TypeDescriptor.TYPE;
            _type = clazz;
            return(new TypedValue(clazz));
        }
Exemple #2
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));
        }