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)); }
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)); }