Example #1
0
        /// <summary>
        /// Creates an array of the given type from the given arguments
        /// </summary>
        /// <param name="type"></param>
        /// <param name="arguments"></param>
        /// <param name="ctx"></param>
        /// <returns></returns>
        public static object CreateArray(Type type, object[] arguments, IContextObject ctx)
        {
            Type             elementType = type.GetElementType();
            IObjectConverter converter   = ctx.Registry.GetConverter(elementType);

            string failedConvert = $"Failed to convert '{string.Join(" ", arguments)}' to Type {type.Name}.";
            string failedCreate  = $"failed to create an instance of type {elementType.Name} from argument ";

            //Create the generic array of the required size
            Array array = (Array)Activator.CreateInstance(type, arguments.Length);

            for (int i = 0; i < array.Length; i++)
            {
                if (converter != null)
                {
                    //if we have a converter, use it
                    object conversion = converter.ConvertFromString(arguments[i].ToString(), ctx);

                    if (conversion == null)
                    {
                        throw new CommandParsingException(
                                  ParserFailReason.ParsingFailed,
                                  failedConvert,
                                  new Exception($"Conversion failed by '{converter.GetType().Name}.'")
                                  );
                    }

                    array.SetValue(conversion, i);
                    continue;
                }

                if (elementType == typeof(string))
                {
                    //strings are special, so have special treatment
                    array.SetValue(arguments[i], i);
                    continue;
                }

                if (elementType.GetTypeInfo().IsValueType)
                {
                    //value types can be created with a typeconverter
                    TypeConverter tc = TypeDescriptor.GetConverter(type.GetElementType());
                    try
                    {
                        //but a bad argument will throw an exception, so handle that
                        array.SetValue(tc.ConvertFrom(arguments[i]), i);
                    }
                    catch (Exception e)
                    {
                        throw new CommandParsingException(ParserFailReason.ParsingFailed, $"TypeConverter {failedCreate} '{arguments[i]}'.", e);
                    }
                }
                else
                {
                    //reference types need to be created with the Activator
                    try
                    {
                        //once again, bad arguments can throw an exception
                        object element = Activator.CreateInstance(elementType, arguments[i]);
                        array.SetValue(element, i);
                    }
                    catch (Exception e)
                    {
                        throw new CommandParsingException(ParserFailReason.ParsingFailed, $"Activator {failedCreate} '{arguments[i]}'.", e);
                    }
                }
            }

            return(array);
        }
Example #2
0
        /// <summary>
        /// Attempts to convert the arguments provided into objects of types required by the command executor
        /// </summary>
        /// <param name="ctx"></param>
        protected override void ConvertArgumentsToTypes(IContextObject ctx)
        {
            Objects = new List <object> {
                ctx
            };
            int index = 0;
            IEnumerable <object> arguments = Input.ObjectiveExplode();

            if (AdditionalArgs != null)
            {
                arguments = arguments.Concat(AdditionalArgs);
            }

            foreach (KeyValuePair <ParameterInfo, CommandParameterAttribute> kvp in ExecutorData.ParameterData)
            {
                //Get the number of arguments going in to the parameter
                int count = kvp.Value.Repetitions <= 0 ? arguments.Count() - index
                                                        : kvp.Value.Repetitions;

                if (index >= arguments.Count())
                {
                    //If we've used all our arguments, just add empty ones to satisfy the
                    //method signature for the command
                    Objects.Add(ObjectCreator.CreateDefaultObject(kvp.Key));
                    continue;
                }

                object[] args = arguments.ReadToArray(index, count);

                //If the provided object is already of the required type, add and continue
                if (count == 1 && args[0].GetType() == kvp.Key.ParameterType)
                {
                    Objects.Add(args[0]);
                    continue;
                }

                IObjectConverter converter = Registry.GetConverter(kvp.Key.ParameterType);
                if (converter == null)
                {
                    //Use the object creator to attempt a conversion
                    Objects.Add(ObjectCreator.CreateObject(kvp.Key.ParameterType, args, ctx));
                }
                else
                {
                    //Use a defined converter.
                    object conversion = count > 1 ? converter.ConvertFromArray((string[])args, ctx)
                                                  : converter.ConvertFromString(args[0].ToString(), ctx);

                    if (conversion == null)
                    {
                        throw new CommandParsingException(
                                  ParserFailReason.ParsingFailed,
                                  $"Type conversion failed: Failed to convert '{string.Join(" ", args)}' to Type '{ kvp.Key.ParameterType.Name }'.",
                                  new Exception($"Conversion failed in '{converter.GetType().Name}.{nameof(IObjectConverter.ConvertFromArray)}'")
                                  );
                    }

                    Objects.Add(conversion);
                }

                index += count;
            }
        }