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()); }
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; }
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); }
/// <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); } } }
/// <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);
//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);
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; } }
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; }
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); } }
public void AddTypeReader(Type type, TypeReader reader) { var readers = _typeReaders.GetOrAdd(type, x => new ConcurrentDictionary <Type, TypeReader>()); readers[reader.GetType()] = reader; }
public void AddTypeReader(Type type, TypeReader reader) { _typeReaders[type] = reader; }
public void AddTypeReader <T>(TypeReader reader) { _typeReaders[typeof(T)] = reader; }