private static void BuildParameter(ParameterBuilder builder, System.Reflection.ParameterInfo paramInfo, int position, int count, CommandService service)
        {
            var attributes = paramInfo.GetCustomAttributes();
            var paramType  = paramInfo.ParameterType;

            builder.Name = paramInfo.Name;

            builder.IsOptional   = paramInfo.IsOptional;
            builder.DefaultValue = paramInfo.HasDefaultValue ? paramInfo.DefaultValue : null;

            foreach (var attribute in attributes)
            {
                // TODO: C#7 type switch
                if (attribute is SummaryAttribute)
                {
                    builder.Summary = (attribute as SummaryAttribute).Text;
                }
                else if (attribute is OverrideTypeReaderAttribute)
                {
                    builder.TypeReader = GetTypeReader(service, paramType, (attribute as OverrideTypeReaderAttribute).TypeReader);
                }
                else if (attribute is ParameterPreconditionAttribute)
                {
                    builder.AddPrecondition(attribute as ParameterPreconditionAttribute);
                }
                else if (attribute is ParamArrayAttribute)
                {
                    builder.IsMultiple = true;
                    paramType          = paramType.GetElementType();
                }
                else if (attribute is RemainderAttribute)
                {
                    if (position != count - 1)
                    {
                        throw new InvalidOperationException("Remainder parameters must be the last parameter in a command.");
                    }

                    builder.IsRemainder = true;
                }
            }

            builder.ParameterType = paramType;

            if (builder.TypeReader == null)
            {
                var        readers = service.GetTypeReaders(paramType);
                TypeReader reader  = null;

                if (readers != null)
                {
                    reader = readers.FirstOrDefault().Value;
                }
                else
                {
                    reader = service.GetDefaultTypeReader(paramType);
                }

                builder.TypeReader = reader;
            }
        }
        private static void BuildParameter(ParameterBuilder builder, System.Reflection.ParameterInfo paramInfo, int position, int count, CommandService service, IServiceProvider services)
        {
            var attributes = paramInfo.GetCustomAttributes();
            var paramType  = paramInfo.ParameterType;

            builder.Name = paramInfo.Name;

            builder.IsOptional   = paramInfo.IsOptional;
            builder.DefaultValue = paramInfo.HasDefaultValue ? paramInfo.DefaultValue : null;

            foreach (var attribute in attributes)
            {
                switch (attribute)
                {
                case SummaryAttribute summary:
                    builder.Summary = summary.Text;
                    break;

                case OverrideTypeReaderAttribute typeReader:
                    builder.TypeReader = GetTypeReader(service, paramType, typeReader.TypeReader, services);
                    break;

                case ParamArrayAttribute _:
                    builder.IsMultiple = true;
                    paramType          = paramType.GetElementType();
                    break;

                case ParameterPreconditionAttribute precon:
                    builder.AddPrecondition(precon);
                    break;

                case NameAttribute name:
                    builder.Name = name.Text;
                    break;

                case RemainderAttribute _:
                    if (position != count - 1)
                    {
                        throw new InvalidOperationException($"Remainder parameters must be the last parameter in a command. Parameter: {paramInfo.Name} in {paramInfo.Member.DeclaringType.Name}.{paramInfo.Member.Name}");
                    }

                    builder.IsRemainder = true;
                    break;

                default:
                    builder.AddAttributes(attribute);
                    break;
                }
            }

            builder.ParameterType = paramType;

            if (builder.TypeReader == null)
            {
                builder.TypeReader = service.GetDefaultTypeReader(paramType)
                                     ?? service.GetTypeReaders(paramType)?.FirstOrDefault().Value;
            }
        }
示例#3
0
        private static TypeReader GetTypeReader(CommandService service, Type paramType, Type typeReaderType, IServiceProvider services)
        {
            var        readers = service.GetTypeReaders(paramType);
            TypeReader reader  = null;

            if (readers != null)
            {
                if (readers.TryGetValue(typeReaderType, out reader))
                {
                    return(reader);
                }
            }

            //We dont have a cached type reader, create one
            reader = ReflectionUtils.CreateObject <TypeReader>(typeReaderType.GetTypeInfo(), service, services);
            service.AddTypeReader(paramType, reader);

            return(reader);
        }
        public override async Task <TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services)
        {
            T         result = new T();
            ReadState state = ReadState.LookingForParameter;
            int       beginRead = 0, currentRead = 0;

            while (state != ReadState.End)
            {
                try
                {
                    PropertyInfo prop    = Read(out string arg);
                    object       propVal = await ReadArgumentAsync(prop, arg).ConfigureAwait(false);

                    if (propVal != null)
                    {
                        prop.SetMethod.Invoke(result, new[] { propVal });
                    }
                    else
                    {
                        return(TypeReaderResult.FromError(CommandError.ParseFailed, $"Could not parse the argument for the parameter '{prop.Name}' as type '{prop.PropertyType}'."));
                    }
                }
                catch (Exception ex)
                {
                    return(TypeReaderResult.FromError(ex));
                }
            }

            return(TypeReaderResult.FromSuccess(result));

            PropertyInfo Read(out string arg)
            {
                string currentParam = null;
                char   match        = '\0';

                for (; currentRead < input.Length; currentRead++)
                {
                    char currentChar = input[currentRead];
                    switch (state)
                    {
                    case ReadState.LookingForParameter:
                        if (Char.IsWhiteSpace(currentChar))
                        {
                            continue;
                        }
                        else
                        {
                            beginRead = currentRead;
                            state     = ReadState.InParameter;
                        }
                        break;

                    case ReadState.InParameter:
                        if (currentChar != ':')
                        {
                            continue;
                        }
                        else
                        {
                            currentParam = input.Substring(beginRead, currentRead - beginRead);
                            state        = ReadState.LookingForArgument;
                        }
                        break;

                    case ReadState.LookingForArgument:
                        if (Char.IsWhiteSpace(currentChar))
                        {
                            continue;
                        }
                        else
                        {
                            beginRead = currentRead;
                            state     = (QuotationAliasUtils.GetDefaultAliasMap.TryGetValue(currentChar, out match))
                                    ? ReadState.InQuotedArgument
                                    : ReadState.InArgument;
                        }
                        break;

                    case ReadState.InArgument:
                        if (!Char.IsWhiteSpace(currentChar))
                        {
                            continue;
                        }
                        else
                        {
                            return(GetPropAndValue(out arg));
                        }

                    case ReadState.InQuotedArgument:
                        if (currentChar != match)
                        {
                            continue;
                        }
                        else
                        {
                            return(GetPropAndValue(out arg));
                        }
                    }
                }

                if (currentParam == null)
                {
                    throw new InvalidOperationException("No parameter name was read.");
                }

                return(GetPropAndValue(out arg));

                PropertyInfo GetPropAndValue(out string argv)
                {
                    bool quoted = state == ReadState.InQuotedArgument;

                    state = (currentRead == (quoted ? input.Length - 1 : input.Length))
                        ? ReadState.End
                        : ReadState.LookingForParameter;

                    if (quoted)
                    {
                        argv = input.Substring(beginRead + 1, currentRead - beginRead - 1).Trim();
                        currentRead++;
                    }
                    else
                    {
                        argv = input.Substring(beginRead, currentRead - beginRead);
                    }

                    return(_tProps[currentParam]);
                }
            }

            async Task <object> ReadArgumentAsync(PropertyInfo prop, string arg)
            {
                Type elemType     = prop.PropertyType;
                bool isCollection = false;

                if (elemType.GetTypeInfo().IsGenericType&& elemType.GetGenericTypeDefinition() == typeof(IEnumerable <>))
                {
                    elemType     = prop.PropertyType.GenericTypeArguments[0];
                    isCollection = true;
                }

                OverrideTypeReaderAttribute overridden = prop.GetCustomAttribute <OverrideTypeReaderAttribute>();
                TypeReader reader = (overridden != null)
                    ? ModuleClassBuilder.GetTypeReader(_commands, elemType, overridden.TypeReader, services)
                    : (_commands.GetDefaultTypeReader(elemType)
                       ?? _commands.GetTypeReaders(elemType).FirstOrDefault().Value);

                if (reader != null)
                {
                    if (isCollection)
                    {
                        MethodInfo         method = _readMultipleMethod.MakeGenericMethod(elemType);
                        Task <IEnumerable> task   = (Task <IEnumerable>)method.Invoke(null, new object[] { reader, context, arg.Split(','), services });
                        return(await task.ConfigureAwait(false));
                    }
                    else
                    {
                        return(await ReadSingle(reader, context, arg, services).ConfigureAwait(false));
                    }
                }
                return(null);
            }
        }