private static async Task <IEnumerable> ReadMultiple <TObj>(TypeReader reader, ICommandContext context, IEnumerable <string> args, IServiceProvider services)
        {
            List <TObj> objs = new List <TObj>();

            foreach (string arg in args)
            {
                object read = await ReadSingle(reader, context, arg.Trim(), services).ConfigureAwait(false);

                if (read != null)
                {
                    objs.Add((TObj)read);
                }
            }
            return(objs.ToImmutableArray());
        }
示例#2
0
        internal ParameterInfo(ParameterBuilder builder, CommandInfo command, CommandService service)
        {
            Command = command;

            Name        = builder.Name;
            Summary     = builder.Summary;
            IsOptional  = builder.IsOptional;
            IsRemainder = builder.IsRemainder;
            IsMultiple  = builder.IsMultiple;

            Type         = builder.ParameterType;
            DefaultValue = builder.DefaultValue;

            Preconditions = builder.Preconditions.ToImmutableArray();

            _reader = builder.TypeReader;
        }
示例#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);
        }
示例#4
0
        /// <summary>
        ///     Adds a custom <see cref="TypeReader" /> to this <see cref="CommandService" /> for the supplied object
        ///     type.
        ///     If <paramref name="type" /> is a <see cref="ValueType" />, a nullable <see cref="TypeReader" /> for the
        ///     value type will also be added.
        /// </summary>
        /// <param name="type">A <see cref="Type" /> instance for the type to be read.</param>
        /// <param name="reader">An instance of the <see cref="TypeReader" /> to be added.</param>
        /// <param name="replaceDefault">
        ///     Defines whether the <see cref="TypeReader"/> should replace the default one for <see cref="Type" /> if
        ///     it exists.
        /// </param>
        public void AddTypeReader(Type type, TypeReader reader, bool replaceDefault)
        {
            if (replaceDefault && HasDefaultTypeReader(type))
            {
                _defaultTypeReaders.AddOrUpdate(type, reader, (k, v) => reader);
                if (type.GetTypeInfo().IsValueType)
                {
                    var nullableType   = typeof(Nullable <>).MakeGenericType(type);
                    var nullableReader = NullableTypeReader.Create(type, reader);
                    _defaultTypeReaders.AddOrUpdate(nullableType, nullableReader, (k, v) => nullableReader);
                }
            }
            else
            {
                var readers = _typeReaders.GetOrAdd(type, x => new ConcurrentDictionary <Type, TypeReader>());
                readers[reader.GetType()] = reader;

                if (type.GetTypeInfo().IsValueType)
                {
                    AddNullableTypeReader(type, reader);
                }
            }
        }
示例#5
0
 /// <summary>
 ///     Adds a custom <see cref="TypeReader" /> to this <see cref="CommandService" /> for the supplied object
 ///     type.
 ///     If <typeparamref name="T" /> is a <see cref="ValueType" />, a nullable <see cref="TypeReader" /> will
 ///     also be added.
 /// </summary>
 /// <typeparam name="T">The object type to be read by the <see cref="TypeReader"/>.</typeparam>
 /// <param name="reader">An instance of the <see cref="TypeReader" /> to be added.</param>
 /// <param name="replaceDefault">
 ///     Defines whether the <see cref="TypeReader"/> should replace the default one for
 ///     <see cref="Type" /> if it exists.
 /// </param>
 public void AddTypeReader <T>(TypeReader reader, bool replaceDefault)
 => AddTypeReader(typeof(T), reader, replaceDefault);
示例#6
0
 //Type Readers
 /// <summary>
 ///     Adds a custom <see cref="TypeReader" /> to this <see cref="CommandService" /> for the supplied object
 ///     type.
 ///     If <typeparamref name="T" /> is a <see cref="ValueType" />, a nullable <see cref="TypeReader" /> will
 ///     also be added.
 ///     If a default <see cref="TypeReader" /> exists for <typeparamref name="T" />, a warning will be logged
 ///     and the default <see cref="TypeReader" /> will be replaced.
 /// </summary>
 /// <typeparam name="T">The object type to be read by the <see cref="TypeReader"/>.</typeparam>
 /// <param name="reader">An instance of the <see cref="TypeReader" /> to be added.</param>
 public void AddTypeReader <T>(TypeReader reader)
 => AddTypeReader(typeof(T), reader);
示例#7
0
        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)
            {
                var        readers = service.GetTypeReaders(paramType);
                TypeReader reader  = null;

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

                builder.TypeReader = reader;
            }
        }
示例#8
0
 public CommandParameter(ParameterInfo source, string name, string summary, Type type, TypeReader reader, bool isOptional, bool isRemainder, bool isMultiple, object defaultValue)
 {
     Source       = source;
     Name         = name;
     Summary      = summary;
     ElementType  = type;
     _reader      = reader;
     IsOptional   = isOptional;
     IsRemainder  = isRemainder;
     IsMultiple   = isMultiple;
     DefaultValue = defaultValue;
 }
示例#9
0
        public static TypeReader Create(Type type, TypeReader reader)
        {
            var constructor = typeof(NullableTypeReader <>).MakeGenericType(type).GetTypeInfo().DeclaredConstructors.First();

            return((TypeReader)constructor.Invoke(new object[] { 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);
            }
        }
示例#11
0
        public void AddTypeReader(Type type, TypeReader reader)
        {
            var readers = _typeReaders.GetOrAdd(type, x => new ConcurrentDictionary <Type, TypeReader>());

            readers[reader.GetType()] = reader;
        }
示例#12
0
 public void AddTypeReader(Type type, TypeReader reader)
 {
     _typeReaders[type] = reader;
 }
示例#13
0
 public void AddTypeReader <T>(TypeReader reader)
 {
     _typeReaders[typeof(T)] = reader;
 }