You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
4.5 KiB
137 lines
4.5 KiB
4 years ago
|
using System;
|
||
|
using System.Linq;
|
||
|
using System.Reflection;
|
||
|
|
||
|
using System.Collections.Generic;
|
||
|
|
||
|
namespace Discord.Commands.Builders
|
||
|
{
|
||
|
public class 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;
|
||
|
|
||
|
//Automatic
|
||
|
internal ParameterBuilder(CommandBuilder command)
|
||
|
{
|
||
|
_preconditions = new List<ParameterPreconditionAttribute>();
|
||
|
_attributes = new List<Attribute>();
|
||
|
|
||
|
Command = command;
|
||
|
}
|
||
|
//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)
|
||
|
type = ParameterType.GetElementType();
|
||
|
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 ?? (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);
|
||
|
}
|
||
|
}
|
||
|
}
|