- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
-
- namespace Discord.Commands.Builders
- {
- public class ParameterBuilder
- {
- #region ParameterBuilder
- private readonly List<ParameterPreconditionAttribute> _preconditions;
- private readonly List<Attribute> _attributes;
-
- public CommandBuilder Command { get; }
- public string Name { get; internal set; }
- public Type ParameterType { get; internal set; }
-
- public TypeReader TypeReader { get; set; }
- public bool IsOptional { get; set; }
- public bool IsRemainder { get; set; }
- public bool IsMultiple { get; set; }
- public object DefaultValue { get; set; }
- public string Summary { get; set; }
-
- public IReadOnlyList<ParameterPreconditionAttribute> Preconditions => _preconditions;
- public IReadOnlyList<Attribute> Attributes => _attributes;
- #endregion
-
- #region Automatic
- internal ParameterBuilder(CommandBuilder command)
- {
- _preconditions = new List<ParameterPreconditionAttribute>();
- _attributes = new List<Attribute>();
-
- Command = command;
- }
- #endregion
-
- #region User-defined
- internal ParameterBuilder(CommandBuilder command, string name, Type type)
- : this(command)
- {
- Discord.Preconditions.NotNull(name, nameof(name));
-
- Name = name;
- SetType(type);
- }
-
- internal void SetType(Type type)
- {
- TypeReader = GetReader(type);
-
- if (type.GetTypeInfo().IsValueType)
- DefaultValue = Activator.CreateInstance(type);
- else if (type.IsArray)
- DefaultValue = Array.CreateInstance(type.GetElementType(), 0);
- ParameterType = type;
- }
-
- private TypeReader GetReader(Type type)
- {
- var commands = Command.Module.Service;
- if (type.GetTypeInfo().GetCustomAttribute<NamedArgumentTypeAttribute>() != null)
- {
- IsRemainder = true;
- var reader = commands.GetTypeReaders(type)?.FirstOrDefault().Value;
- if (reader == null)
- {
- Type readerType;
- try
- {
- readerType = typeof(NamedArgumentTypeReader<>).MakeGenericType(new[] { type });
- }
- catch (ArgumentException ex)
- {
- throw new InvalidOperationException($"Parameter type '{type.Name}' for command '{Command.Name}' must be a class with a public parameterless constructor to use as a NamedArgumentType.", ex);
- }
-
- reader = (TypeReader)Activator.CreateInstance(readerType, new[] { commands });
- commands.AddTypeReader(type, reader);
- }
-
- return reader;
- }
-
-
- var readers = commands.GetTypeReaders(type);
- if (readers != null)
- return readers.FirstOrDefault().Value;
- else
- return commands.GetDefaultTypeReader(type);
- }
-
- public ParameterBuilder WithSummary(string summary)
- {
- Summary = summary;
- return this;
- }
- public ParameterBuilder WithDefault(object defaultValue)
- {
- DefaultValue = defaultValue;
- return this;
- }
- public ParameterBuilder WithIsOptional(bool isOptional)
- {
- IsOptional = isOptional;
- return this;
- }
- public ParameterBuilder WithIsRemainder(bool isRemainder)
- {
- IsRemainder = isRemainder;
- return this;
- }
- public ParameterBuilder WithIsMultiple(bool isMultiple)
- {
- IsMultiple = isMultiple;
- return this;
- }
-
- public ParameterBuilder AddAttributes(params Attribute[] attributes)
- {
- _attributes.AddRange(attributes);
- return this;
- }
- public ParameterBuilder AddPrecondition(ParameterPreconditionAttribute precondition)
- {
- _preconditions.Add(precondition);
- return this;
- }
-
- internal ParameterInfo Build(CommandInfo info)
- {
- if ((TypeReader ??= GetReader(ParameterType)) == null)
- throw new InvalidOperationException($"No type reader found for type {ParameterType.Name}, one must be specified");
-
- return new ParameterInfo(this, info, Command.Module.Service);
- }
- #endregion
- }
- }
|