/// <summary>
        /// Gets the effective Value of this ScriptValue instance
        /// </summary>
        /// <param name="arguments">indexer/method/constructor arguments</param>
        /// <returns>an object that represents the value of this ScriptValue</returns>
        public virtual object GetValue(ScriptValue[] arguments)
        {
            if (!Getable)
            {
                throw new ScriptException("Get is not supported for this member");
            }

            if (creator != null)
            {
                bool ok;
                object retVal = creator.InvokeExecutor(Value, arguments, bypassCompatibilityOnLazyInvokation, out ok);
                if (ok)
                {
                    return retVal;
                }
            }

            if (ValueType == ValueType.Literal)
            {
                return Value;
            }

            object tmpValue = Value;
            if (ValueType == ValueType.PropertyOrField)
            {
                if (arguments == null || arguments.Length == 0)
                {
                    var invokationHelper = tmpValue as InvokationHelper;
                    if (invokationHelper != null)
                    {
                        bool ok;
                        object retVal = invokationHelper.Invoke(null, out ok);
                        if (ok)
                        {
                            return retVal;
                        }
                    }

                    FunctionLiteral fx = tmpValue as FunctionLiteral;
                    if (fx != null && fx.AutoInvokeEnabled)
                    {
                        return ((FunctionLiteral) tmpValue).Invoke(null);
                    }

                    return tmpValue;
                }
                if (tmpValue == null)
                {
                    throw new ScriptException("Indexer Failed for NULL - Value");
                }

                if (tmpValue is Type)
                {
                    throw new ScriptException("Indexer call for Types not supported");
                }

                object[] parameters = (from t in arguments select t.GetValue(null)).ToArray();
                if (!(tmpValue is Array))
                {
                    object[] args;
                    Type targetType = tmpValue.GetType();
                    if (ExplicitType != null)
                    {
                        if (!ExplicitType.IsAssignableFrom(targetType))
                        {
                            throw new ScriptException("Provided Type is not implemented by the target-object");
                        }

                        targetType = ExplicitType;
                    }
                    PropertyInfo pi = MethodHelper.GetCapableIndexer(targetType,
                                                                     parameters,
                                                                     out args);
                    if (pi == null)
                    {
                        throw new ScriptException("No capable Indexer found for the provided arguments");
                    }

                    if (creator != null)
                    {
                        creator.SetPreferredExecutor(new LazyIndexer(pi,parameters.Length != args.Length));
                    }

                    return pi.GetValue(tmpValue, args);
                }

                Array arr = (Array)tmpValue;
                return arr.GetValue(parameters.Cast<int>().ToArray());
            }

            if (ValueType == ValueType.Method)
            {
                SequenceValue ta = (SequenceValue) arguments[0];
                SequenceValue a = (SequenceValue) arguments[1];
                ScriptValue et = arguments[2];
                Type explicitType = null;
                object[] parameters = (from t in a.Sequence select t.GetValue(null)).ToArray();
                Type[] typeParameters = Type.EmptyTypes;
                if (ta != null)
                {
                    typeParameters = (from t in ta.Sequence select (Type) t.GetValue(null)).ToArray();
                }

                if (et != null)
                {
                    explicitType = et.GetValue(null) as Type;
                }

                Type type;
                
                if (tmpValue == null)
                {
                    ValueType = ValueType.PropertyOrField;
                }

                if (Name == null)
                {
                    try
                    {
                        if (tmpValue is Delegate)
                        {
                            Delegate dlg = (Delegate) tmpValue;
                            return dlg.DynamicInvoke(parameters);
                        }

                        if (tmpValue is InvokationHelper)
                        {
                            InvokationHelper ih = (InvokationHelper) tmpValue;
                            bool ok;
                            var retVal = ih.Invoke(parameters, out ok);
                            if (ok)
                            {
                                return retVal;
                            }

                            throw new ScriptException($"Failed to call method {Name}. Possible Arguments-mismatch.");
                        }

                        if (tmpValue is FunctionLiteral)
                        {
                            FunctionLiteral fl = (FunctionLiteral) tmpValue;
                            return fl.Invoke(parameters);
                        }
                    }
                    finally
                    {
                        ValueType = ValueType.Method;
                    }
                }

                if (tmpValue == null)
                {
                    throw new Exception("Method call failed for NULL - Value");
                }

                object target = tmpValue;
                bool isStatic = false;
                if (tmpValue is Type)
                {
                    type = (Type)tmpValue;
                    target = null;
                    isStatic = true;
                }
                else if (tmpValue is ObjectLiteral)
                {
                    type = tmpValue.GetType();
                    ObjectLiteral ol = tmpValue as ObjectLiteral;
                    FunctionLiteral fl = ol[Name] as FunctionLiteral;
                    if (fl != null)
                    {
                        return fl.Invoke(parameters);
                    }
                }
                else
                {
                    type = explicitType??tmpValue.GetType();
                }

                object[] args;
#if UseDelegates
                MethodInvoker method = MethodHelper.GetCapableMethod(type, typeParameters, Name, Value is Type, parameters, out args);
#else
                bool tmpStatic = isStatic;
                MethodInfo method = MethodHelper.GetCapableMethod(type, typeParameters, Name, ref isStatic, parameters,
                                                                  out args);
                if (!tmpStatic && isStatic)
                {
                    args[0] = target;
                    target = null;
                }
#endif
                if (method == null)
                {
                    throw new ScriptException(string.Format("No capable Method found for {0}", Name));
                }

                var writeBacks = MethodHelper.GetWritebacks(method, args, a.Sequence);
                if (creator != null)
                {
                    creator.SetPreferredExecutor(new LazyMethod(method, tmpStatic, !tmpStatic && isStatic, args.Length != a.Sequence.Length));
                }
#if UseDelegates
                if (target != null)
                {
                    target = target.WrapIfValueType();
                }

                return method(target, args);
                if (target != null)
                {

                    /*object[] newArgs = new object[args.Length + 1];
                    newArgs[0] = target;
                    Array.Copy(args, 0, newArgs, 1, args.Length);*/
                    args[0] = target;
                    if (!(target is System.ValueType))
                    {
                        return method.FastDynamicInvoke(args);
                    }

                    return method.DynamicInvoke(args);
#else
                try
                {
                    return method.Invoke(target, args);
                }
                finally
                {
                    foreach (var wb in writeBacks)
                    {
                        wb.Target.SetValue(args[wb.Index]);
                    }
                }
#endif
#if UseDelegates
                }


                return method.FastDynamicInvoke(args);
#endif
            }

            if (ValueType == ValueType.Constructor)
            {
                if (tmpValue == null || !(tmpValue is Type))
                {
                    throw new ScriptException("Require Type in order to create a new instance");
                }

                ScriptValue[] ta = null;
                if (arguments[0] != null)
                {
                    ta = ((SequenceValue)arguments[0]).Sequence;
                }

                ScriptValue[] a = ((SequenceValue) arguments[1]).Sequence;
                object[] parameters = (from t in a select t.GetValue(null)).ToArray();
                Type[] typeParameters = ta == null
                                            ? Type.EmptyTypes
                                            : (from t in ta select (Type) t.GetValue(null)).ToArray();
                Type type = (Type)tmpValue;
                if (typeParameters.Length != 0)
                {
                    //throw new ScriptException(string.Format("Unexpected usage of generic Type {0}", ((Type)Value).FullName));
                    type = type.MakeGenericType(typeParameters);
                }

                object[] args;
                ConstructorInfo constructor = MethodHelper.GetCapableConstructor(type, parameters, out args);
                if (constructor == null)
                {
                    throw new ScriptException(string.Format("No appropriate Constructor was found for {0}",
                                                            ((Type)tmpValue).FullName));
                }

                if (creator != null)
                {
                    creator.SetPreferredExecutor(new LazyConstructor(constructor, args.Length != a.Length));
                }

                return constructor.Invoke(args);
            }

            throw new ScriptException("Unexpected Value-Type");
        }
        public bool CanGetValue(ScriptValue[] arguments)
        {
            if (!Getable)
            {
                throw new ScriptException("Get is not supported for this member");
            }

            if (creator != null)
            {
                bool ok = creator.CanInvokeExecutor(Value,arguments,bypassCompatibilityOnLazyInvokation);
                //object retVal = creator.InvokeExecutor(Value, arguments, bypassCompatibilityOnLazyInvokation, out ok);
                if (ok)
                {
                    return true;
                }
            }

            if (ValueType == ValueType.Literal)
            {
                return false;
            }

            object tmpValue = Value;
            if (ValueType == ValueType.PropertyOrField)
            {
                if (arguments == null || arguments.Length == 0)
                {
                    return true;
                }
                if (tmpValue == null)
                {
                    return false;
                }

                if (tmpValue is Type)
                {
                    return false;
                }

                object[] parameters = (from t in arguments select t.GetValue(null)).ToArray();
                if (!(tmpValue is Array))
                {
                    object[] args;
                    PropertyInfo pi = MethodHelper.GetCapableIndexer(ExplicitType??tmpValue.GetType(),
                                                                     parameters,
                                                                     out args);
                    return pi != null;
                }

                Array arr = (Array)tmpValue;
                int[] indices = parameters.Cast<int>().ToArray();
                bool retVal = true;
                for (int i = 0; i < indices.Length; i++)
                {
                    retVal &= arr.GetLength(i) > indices[i];
                }

                return retVal;
            }

            if (ValueType == ValueType.Method)
            {
                SequenceValue ta = (SequenceValue)arguments[0];
                SequenceValue a = (SequenceValue)arguments[1];
                ScriptValue et = arguments[2];
                object[] parameters = (from t in a.Sequence select t.GetValue(null)).ToArray();
                Type[] typeParameters = Type.EmptyTypes;
                if (ta != null)
                {
                    typeParameters = (from t in ta.Sequence select (Type)t.GetValue(null)).ToArray();
                }

                Type type;

                if (tmpValue == null)
                {
                    ValueType = ValueType.PropertyOrField;
                }

                if (Name == null)
                {
                    try
                    {
                        if (tmpValue is Delegate)
                        {
                            return true;
                        }

                        if (tmpValue is InvokationHelper)
                        {
                            return true;
                        }

                        if (tmpValue is FunctionLiteral)
                        {
                            return true;
                        }
                    }
                    finally
                    {
                        ValueType = ValueType.Method;
                    }
                }

                if (tmpValue == null)
                {
                    return false;
                }

                object target = tmpValue;
                bool isStatic = false;
                if (tmpValue is Type)
                {
                    type = (Type)tmpValue;
                    target = null;
                    isStatic = true;
                }
                else if (tmpValue is ObjectLiteral)
                {
                    type = tmpValue.GetType();
                    ObjectLiteral ol = tmpValue as ObjectLiteral;
                    FunctionLiteral fl = ol[Name] as FunctionLiteral;
                    if (fl != null)
                    {
                        return true;
                    }
                }
                else
                {
                    type = et?.GetValue(null) as Type ?? tmpValue.GetType();
                }

                object[] args;
#if UseDelegates
                MethodInvoker method = MethodHelper.GetCapableMethod(type, typeParameters, Name, Value is Type, parameters, out args);
#else
                bool tmpStatic = isStatic;
                MethodInfo method = MethodHelper.GetCapableMethod(type, typeParameters, Name, ref isStatic, parameters,
                                                                  out args);
                if (!tmpStatic && isStatic)
                {
                    args[0] = target;
                    target = null;
                }
#endif
                if (method == null)
                {
                    return false;
                }

                return true;
            }

            if (ValueType == ValueType.Constructor)
            {
                if (tmpValue == null || !(tmpValue is Type))
                {
                    throw new ScriptException("Require Type in order to create a new instance");
                }

                ScriptValue[] ta = null;
                if (arguments[0] != null)
                {
                    ta = ((SequenceValue)arguments[0]).Sequence;
                }

                ScriptValue[] a = ((SequenceValue)arguments[1]).Sequence;
                object[] parameters = (from t in a select t.GetValue(null)).ToArray();
                Type[] typeParameters = ta == null
                                            ? Type.EmptyTypes
                                            : (from t in ta select (Type)t.GetValue(null)).ToArray();
                Type type = (Type)tmpValue;
                if (typeParameters.Length != 0)
                {
                    //throw new ScriptException(string.Format("Unexpected usage of generic Type {0}", ((Type)Value).FullName));
                    type = type.MakeGenericType(typeParameters);
                }

                object[] args;
                ConstructorInfo constructor = MethodHelper.GetCapableConstructor(type, parameters, out args);
                if (constructor == null)
                {
                    return false;
                }

                return true;
            }

            throw new ScriptException("Unexpected Value-Type");
        }