/// <summary> /// invokes the method on the object passed in /// </summary> public override Object Execute(Object o, IInternalContextAdapter context) { bool isString = o.GetType() == typeof(string); bool isDecimal = o.GetType() == typeof(decimal); bool isPrimitive = o.GetType().IsPrimitive; if (identifier == "to_quote" && (isString || isPrimitive || isDecimal)) { return(string.Format("\"{0}\"", EscapeDoubleQuote(o.ToString()))); } else if (identifier == "to_squote" && (isString || isPrimitive || isDecimal)) { return(string.Format("'{0}'", EscapeSingleQuote(o.ToString()))); } IDuck duck = o as IDuck; if (duck != null) { return(duck.GetInvoke(identifier)); } IVelPropertyGet velPropertyGet = null; try { Type c = o.GetType(); // first, see if we have this information cached. IntrospectionCacheData introspectionCacheData = context.ICacheGet(this); // if we have the cache data and the class of the object we are // invoked with is the same as that in the cache, then we must // be all-right. The last 'variable' is the method name, and // that is fixed in the template :) if (introspectionCacheData != null && introspectionCacheData.ContextData == c) { velPropertyGet = (IVelPropertyGet)introspectionCacheData.Thingy; } else { // otherwise, do the introspection, and cache it velPropertyGet = runtimeServices.Uberspect.GetPropertyGet(o, identifier, uberInfo); if (velPropertyGet != null && velPropertyGet.Cacheable) { introspectionCacheData = new IntrospectionCacheData(c, velPropertyGet); context.ICachePut(this, introspectionCacheData); } } } catch (Exception e) { runtimeServices.Error(string.Format("ASTIdentifier.execute() : identifier = {0} : {1}", identifier, e)); } // we have no executor... punt... if (velPropertyGet == null) { return(null); } // now try and execute. If we get a TargetInvocationException, // throw that as the app wants to get these. If not, log and punt. try { return(velPropertyGet.Invoke(o)); } catch (TargetInvocationException targetInvocationException) { EventCartridge ec = context.EventCartridge; // if we have an event cartridge, see if it wants to veto // also, let non-Exception Throwables go... if (ec == null) { // no event cartridge to override. Just throw String message = String.Format( "Invocation of method '{0}' in {1}, template {2} Line {3} Column {4} threw an exception", velPropertyGet.MethodName, o != null ? o.GetType().FullName : string.Empty, uberInfo.TemplateName, uberInfo.Line, uberInfo.Column); throw new MethodInvocationException(message, targetInvocationException.InnerException, velPropertyGet.MethodName); } else { try { return(ec.HandleMethodException(o.GetType(), velPropertyGet.MethodName, targetInvocationException.InnerException)); } catch (Exception) { String message = String.Format( "Invocation of method '{0}' in {1}, template {2} Line {3} Column {4} threw an exception", velPropertyGet.MethodName, o != null ? o.GetType().FullName : string.Empty, uberInfo.TemplateName, uberInfo.Line, uberInfo.Column); throw new MethodInvocationException(message, targetInvocationException.InnerException, velPropertyGet.MethodName); } } } catch (ArgumentException) { return(null); } catch (Exception e) { runtimeServices.Error( string.Format("ASTIdentifier() : exception invoking method for identifier '{0}' in {1} : {2}", identifier, o.GetType(), e)); } return(null); }