public void SetValue(Script script, object obj, DynValue value)
        {
            this.CheckAccess(MemberDescriptorAccess.CanWrite, obj);
            var v = ScriptToClrConversions.DynValueToObjectOfType(value, this.MemberType, null, false);

            this.SetValueImpl(script, obj, v);
        }
		/// <summary>
		/// Sets the value of the property
		/// </summary>
		/// <param name="script">The script.</param>
		/// <param name="obj">The object.</param>
		/// <param name="v">The value to set.</param>
		public void SetValue(Script script, object obj, DynValue v)
		{
			this.CheckAccess(MemberDescriptorAccess.CanWrite, obj);

			if (IsReadonly || IsConst)
				throw new ScriptRuntimeException("userdata field '{0}.{1}' cannot be written to.", this.FieldInfo.DeclaringType.Name, this.Name);

			object value = ScriptToClrConversions.DynValueToObjectOfType(v, this.FieldInfo.FieldType, null, false);

			try
			{
				if (value is double)
					value = NumericConversions.DoubleToType(FieldInfo.FieldType, (double)value);

				FieldInfo.SetValue(IsStatic ? null : obj, value);
			}
			catch (ArgumentException)
			{
				// non-optimized setters fall here
				throw ScriptRuntimeException.UserDataArgumentTypeMismatch(v.Type, FieldInfo.FieldType);
			}
			catch (InvalidCastException)
			{
				// optimized setters fall here
				throw ScriptRuntimeException.UserDataArgumentTypeMismatch(v.Type, FieldInfo.FieldType);
			}
			catch (FieldAccessException ex)
			{
				throw new ScriptRuntimeException(ex);
			}
		}
        private static object ArrayIndexerSet(object arrayObj, ScriptExecutionContext ctx, CallbackArguments args)
        {
            var array   = (Array)arrayObj;
            var indices = BuildArrayIndices(args, args.Count - 1);
            var value   = args[args.Count - 1];

            var elemType = array.GetType().GetElementType();

            var objValue = ScriptToClrConversions.DynValueToObjectOfType(value, elemType, null, false);

            array.SetValue(objValue, indices);

            return(DynValue.Void);
        }
        /// <summary>
        /// Sets the value of the property
        /// </summary>
        /// <param name="script">The script.</param>
        /// <param name="obj">The object.</param>
        /// <param name="v">The value to set.</param>
        public void SetValue(Script script, object obj, DynValue v)
        {
            this.CheckAccess(MemberDescriptorAccess.CanWrite, obj);

            if (m_Setter == null)
            {
                throw new ScriptRuntimeException("userdata property '{0}.{1}' cannot be written to.",
                                                 this.PropertyInfo.DeclaringType.Name, this.Name);
            }

            var value = ScriptToClrConversions.DynValueToObjectOfType(v, this.PropertyInfo.PropertyType, null, false);

            try
            {
                if (value is double d)
                {
                    value = NumericConversions.DoubleToType(this.PropertyInfo.PropertyType, d);
                }

                if (this.AccessMode == InteropAccessMode.LazyOptimized && m_OptimizedSetter == null)
                {
                    this.OptimizeSetter();
                }

                if (m_OptimizedSetter != null)
                {
                    m_OptimizedSetter(obj, value);
                }
                else
                {
                    m_Setter.Invoke(this.IsStatic ? null : obj,
                                    new[] { value }); // convoluted workaround for --full-aot Mono execution
                }
            }
            catch (ArgumentException)
            {
                // non-optimized setters fall here
                throw ScriptRuntimeException.UserDataArgumentTypeMismatch(v.Type, this.PropertyInfo.PropertyType);
            }
            catch (InvalidCastException)
            {
                // optimized setters fall here
                throw ScriptRuntimeException.UserDataArgumentTypeMismatch(v.Type, this.PropertyInfo.PropertyType);
            }
        }
        /// <summary>
        /// Builds the argument list.
        /// </summary>
        /// <param name="script">The script.</param>
        /// <param name="obj">The object.</param>
        /// <param name="context">The context.</param>
        /// <param name="args">The arguments.</param>
        /// <param name="outParams">Output: A list containing the indices of all "out" parameters, or null if no out parameters are specified.</param>
        /// <returns>The arguments, appropriately converted.</returns>
        protected virtual object[] BuildArgumentList(Script script, object obj, ScriptExecutionContext context, CallbackArguments args,
                                                     out List <int> outParams)
        {
            ParameterDescriptor[] parameters = Parameters;

            object[] pars = new object[parameters.Length];

            int j = args.IsMethodCall ? 1 : 0;

            outParams = null;

            for (int i = 0; i < pars.Length; i++)
            {
                // keep track of out and ref params
                if (parameters[i].Type.IsByRef)
                {
                    if (outParams == null)
                    {
                        outParams = new List <int>();
                    }
                    outParams.Add(i);
                }

                // if an ext method, we have an obj -> fill the first param
                if (ExtensionMethodType != null && obj != null && i == 0)
                {
                    pars[i] = obj;
                    continue;
                }
                // else, fill types with a supported type
                else if (parameters[i].Type == typeof(Script))
                {
                    pars[i] = script;
                }
                else if (parameters[i].Type == typeof(ScriptExecutionContext))
                {
                    pars[i] = context;
                }
                else if (parameters[i].Type == typeof(CallbackArguments))
                {
                    pars[i] = args.SkipMethodCall();
                }
                // else, ignore out params
                else if (parameters[i].IsOut)
                {
                    pars[i] = null;
                }
                else if (i == parameters.Length - 1 && VarArgsArrayType != null)
                {
                    List <DynValue> extraArgs = new List <DynValue>();

                    while (true)
                    {
                        DynValue arg = args.RawGet(j, false);
                        j += 1;
                        if (arg != null)
                        {
                            extraArgs.Add(arg);
                        }
                        else
                        {
                            break;
                        }
                    }

                    // here we have to worry we already have an array.. damn. We only support this for userdata.
                    // remains to be analyzed what's the correct behavior here. For example, let's take a params object[]..
                    // given a single table parameter, should it use it as an array or as an object itself ?
                    if (extraArgs.Count == 1)
                    {
                        DynValue arg = extraArgs[0];

                        if (arg.Type == DataType.UserData && arg.UserData.Object != null)
                        {
                            if (Framework.Do.IsAssignableFrom(VarArgsArrayType, arg.UserData.Object.GetType()))
                            {
                                pars[i] = arg.UserData.Object;
                                continue;
                            }
                        }
                    }

                    // ok let's create an array, and loop
                    Array vararg = Array.CreateInstance(VarArgsElementType, extraArgs.Count);

                    for (int ii = 0; ii < extraArgs.Count; ii++)
                    {
                        vararg.SetValue(ScriptToClrConversions.DynValueToObjectOfType(extraArgs[ii], VarArgsElementType,
                                                                                      null, false), ii);
                    }

                    pars[i] = vararg;
                }
                // else, convert it
                else
                {
                    var arg = args.RawGet(j, false) ?? DynValue.Void;
                    pars[i] = ScriptToClrConversions.DynValueToObjectOfType(arg, parameters[i].Type,
                                                                            parameters[i].DefaultValue, parameters[i].HasDefaultValue);
                    j += 1;
                }
            }

            return(pars);
        }
        /// <summary>
        /// The internal callback which actually executes the method
        /// </summary>
        /// <param name="script">The script.</param>
        /// <param name="obj">The object.</param>
        /// <param name="context">The context.</param>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        internal DynValue Callback(Script script, object obj, ScriptExecutionContext context, CallbackArguments args)
        {
            if (ValueTypeDefaultCtor != null)
            {
                object vto = Activator.CreateInstance(ValueTypeDefaultCtor);
                return(ClrToScriptConversions.ObjectToDynValue(script, vto));
            }

            if (AccessMode == InteropAccessMode.LazyOptimized &&
                m_OptimizedFunc == null && m_OptimizedAction == null)
            {
                Optimize();
            }

            object[] pars = new object[Parameters.Length];

            int j = args.IsMethodCall ? 1 : 0;

            List <int> outParams = null;

            for (int i = 0; i < pars.Length; i++)
            {
                // keep track of out and ref params
                if (Parameters[i].ParameterType.IsByRef)
                {
                    if (outParams == null)
                    {
                        outParams = new List <int>();
                    }
                    outParams.Add(i);
                }

                // if an ext method, we have an obj -> fill the first param
                if (ExtensionMethodType != null && obj != null && i == 0)
                {
                    pars[i] = obj;
                    continue;
                }
                // else, fill types with a supported type
                else if (Parameters[i].ParameterType == typeof(Script))
                {
                    pars[i] = script;
                }
                else if (Parameters[i].ParameterType == typeof(ScriptExecutionContext))
                {
                    pars[i] = context;
                }
                else if (Parameters[i].ParameterType == typeof(CallbackArguments))
                {
                    pars[i] = args.SkipMethodCall();
                }
                // else, ignore out params
                else if (Parameters[i].IsOut)
                {
                    pars[i] = null;
                }
                else if (i == Parameters.Length - 1 && VarArgsArrayType != null)
                {
                    List <DynValue> extraArgs = new List <DynValue>();

                    while (true)
                    {
                        DynValue arg = args.RawGet(j, false);
                        j += 1;
                        if (arg != null)
                        {
                            extraArgs.Add(arg);
                        }
                        else
                        {
                            break;
                        }
                    }

                    // here we have to worry we already have an array.. damn. We only support this for userdata.
                    // remains to be analyzed what's the correct behavior here. For example, let's take a params object[]..
                    // given a single table parameter, should it use it as an array or as an object itself ?
                    if (extraArgs.Count == 1)
                    {
                        DynValue arg = extraArgs[0];

                        if (arg.Type == DataType.UserData && arg.UserData.Object != null)
                        {
                            if (VarArgsArrayType.IsAssignableFrom(arg.UserData.Object.GetType()))
                            {
                                pars[i] = arg.UserData.Object;
                                continue;
                            }
                        }
                    }

                    // ok let's create an array, and loop
                    Array vararg = CreateVarArgArray(extraArgs.Count);

                    for (int ii = 0; ii < extraArgs.Count; ii++)
                    {
                        vararg.SetValue(ScriptToClrConversions.DynValueToObjectOfType(extraArgs[ii], VarArgsElementType,
                                                                                      null, false), ii);
                    }

                    pars[i] = vararg;
                }
                // else, convert it
                else
                {
                    var arg = args.RawGet(j, false) ?? DynValue.Void;
                    pars[i] = ScriptToClrConversions.DynValueToObjectOfType(arg, Parameters[i].ParameterType,
                                                                            Parameters[i].DefaultValue, !Parameters[i].DefaultValue.IsDbNull());
                    j += 1;
                }
            }


            object retv = null;

            if (m_OptimizedFunc != null)
            {
                retv = m_OptimizedFunc(obj, pars);
            }
            else if (m_OptimizedAction != null)
            {
                m_OptimizedAction(obj, pars);
                retv = DynValue.Void;
            }
            else if (m_IsAction)
            {
                MethodInfo.Invoke(obj, pars);
                retv = DynValue.Void;
            }
            else
            {
                if (IsConstructor)
                {
                    retv = ((ConstructorInfo)MethodInfo).Invoke(pars);
                }
                else
                {
                    retv = MethodInfo.Invoke(obj, pars);
                }
            }

            if (outParams == null)
            {
                return(ClrToScriptConversions.ObjectToDynValue(script, retv));
            }
            else
            {
                DynValue[] rets = new DynValue[outParams.Count + 1];

                rets[0] = ClrToScriptConversions.ObjectToDynValue(script, retv);

                for (int i = 0; i < outParams.Count; i++)
                {
                    rets[i + 1] = ClrToScriptConversions.ObjectToDynValue(script, pars[outParams[i]]);
                }

                return(DynValue.NewTuple(rets));
            }
        }
Beispiel #7
0
 /// <summary>
 /// Converts this MoonSharp DynValue to a CLR object of the specified type.
 /// </summary>
 public object ToObject(Type desiredType)
 {
     //Contract.Requires(desiredType != null);
     return(ScriptToClrConversions.DynValueToObjectOfType(this, desiredType, null, false));
 }