private IMethodExecutor FindAccessorForMethod(List <Type> argumentTypes, object targetObject, IEvaluationContext evaluationContext) { AccessException accessException = null; var methodResolvers = evaluationContext.MethodResolvers; foreach (var methodResolver in methodResolvers) { try { var methodExecutor = methodResolver.Resolve(evaluationContext, targetObject, _name, argumentTypes); if (methodExecutor != null) { return(methodExecutor); } } catch (AccessException ex) { accessException = ex; break; } } var method = FormatHelper.FormatMethodForMessage(_name, argumentTypes); var className = FormatHelper.FormatClassNameForMessage(targetObject is Type ? ((Type)targetObject) : targetObject.GetType()); if (accessException != null) { throw new SpelEvaluationException(StartPosition, accessException, SpelMessage.PROBLEM_LOCATING_METHOD, method, className); } else { throw new SpelEvaluationException(StartPosition, SpelMessage.METHOD_NOT_FOUND, method, className); } }
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)); }
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 (accessorToUse is ReflectivePropertyAccessor.OptimalPropertyAccessor || evalContext.PropertyAccessors.Contains(accessorToUse)) { try { accessorToUse.Write(evalContext, contextObject.Value, name, newValue); return; } catch (Exception) { // 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 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 (accessorToUse is ReflectivePropertyAccessor.OptimalPropertyAccessor || evalContext.PropertyAccessors.Contains(accessorToUse)) { try { return(accessorToUse.Read(evalContext, contextObject.Value, name)); } catch (Exception) { // 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 accessor1) { accessor = accessor1.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))); } }