| @@ -13,6 +13,7 @@ namespace Discord.Commands | |||
| private readonly object _instance; | |||
| private readonly Func<IMessage, IReadOnlyList<object>, Task> _action; | |||
| public MethodInfo Source { get; } | |||
| public string Name { get; } | |||
| public string Description { get; } | |||
| public string Summary { get; } | |||
| @@ -21,25 +22,26 @@ namespace Discord.Commands | |||
| public IReadOnlyList<CommandParameter> Parameters { get; } | |||
| public IReadOnlyList<PreconditionAttribute> Preconditions { get; } | |||
| internal Command(Module module, object instance, CommandAttribute attribute, MethodInfo methodInfo, string groupPrefix) | |||
| internal Command(MethodInfo source, Module module, object instance, CommandAttribute attribute, string groupPrefix) | |||
| { | |||
| Source = source; | |||
| Module = module; | |||
| _instance = instance; | |||
| Name = methodInfo.Name; | |||
| Name = source.Name; | |||
| Text = groupPrefix + attribute.Text; | |||
| var description = methodInfo.GetCustomAttribute<DescriptionAttribute>(); | |||
| var description = source.GetCustomAttribute<DescriptionAttribute>(); | |||
| if (description != null) | |||
| Description = description.Text; | |||
| var summary = methodInfo.GetCustomAttribute<SummaryAttribute>(); | |||
| var summary = source.GetCustomAttribute<SummaryAttribute>(); | |||
| if (summary != null) | |||
| Summary = summary.Text; | |||
| Parameters = BuildParameters(methodInfo); | |||
| Preconditions = BuildPreconditions(methodInfo); | |||
| _action = BuildAction(methodInfo); | |||
| Parameters = BuildParameters(source); | |||
| Preconditions = BuildPreconditions(source); | |||
| _action = BuildAction(source); | |||
| } | |||
| public async Task<PreconditionResult> CheckPreconditions(IMessage context) | |||
| @@ -135,7 +137,7 @@ namespace Discord.Commands | |||
| bool isOptional = parameter.IsOptional; | |||
| object defaultValue = parameter.HasDefaultValue ? parameter.DefaultValue : null; | |||
| paramBuilder.Add(new CommandParameter(name, summary, type, reader, isOptional, isRemainder, isMultiple, defaultValue)); | |||
| paramBuilder.Add(new CommandParameter(parameters[i], name, summary, type, reader, isOptional, isRemainder, isMultiple, defaultValue)); | |||
| } | |||
| return paramBuilder.ToImmutable(); | |||
| } | |||
| @@ -1,5 +1,6 @@ | |||
| using System; | |||
| using System.Diagnostics; | |||
| using System.Reflection; | |||
| using System.Threading.Tasks; | |||
| namespace Discord.Commands | |||
| @@ -9,19 +10,21 @@ namespace Discord.Commands | |||
| { | |||
| private readonly TypeReader _reader; | |||
| public ParameterInfo Source { get; } | |||
| public string Name { get; } | |||
| public string Summary { get; } | |||
| public bool IsOptional { get; } | |||
| public bool IsRemainder { get; } | |||
| public bool IsMultiple { get; } | |||
| public Type Type { get; } | |||
| public Type ElementType { get; } | |||
| internal object DefaultValue { get; } | |||
| public CommandParameter(string name, string summary, Type type, TypeReader reader, bool isOptional, bool isRemainder, bool isMultiple, object defaultValue) | |||
| 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; | |||
| Type = type; | |||
| ElementType = type; | |||
| _reader = reader; | |||
| IsOptional = isOptional; | |||
| IsRemainder = isRemainder; | |||
| @@ -123,9 +123,9 @@ namespace Discord.Commands | |||
| if (curPos == endPos) | |||
| { | |||
| Array realParams = Array.CreateInstance(curParam.Type, paramsList.Count); | |||
| Array realParams = Array.CreateInstance(curParam.ElementType, paramsList.Count); | |||
| for (int i = 0; i < paramsList.Count; i++) | |||
| realParams.SetValue(Convert.ChangeType(paramsList[i], curParam.Type), i); | |||
| realParams.SetValue(Convert.ChangeType(paramsList[i], curParam.ElementType), i); | |||
| argList.Add(realParams); | |||
| @@ -120,7 +120,7 @@ namespace Discord.Commands | |||
| if (_modules.ContainsKey(moduleInstance.GetType())) | |||
| return _modules[moduleInstance.GetType()]; | |||
| var loadedModule = new Module(this, moduleInstance, moduleAttr, typeInfo); | |||
| var loadedModule = new Module(typeInfo, this, moduleInstance, moduleAttr); | |||
| _modules[moduleInstance.GetType()] = loadedModule; | |||
| foreach (var cmd in loadedModule.Commands) | |||
| @@ -8,6 +8,7 @@ namespace Discord.Commands | |||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
| public class Module | |||
| { | |||
| public TypeInfo Source { get; } | |||
| public CommandService Service { get; } | |||
| public string Name { get; } | |||
| public string Summary { get; } | |||
| @@ -17,38 +18,39 @@ namespace Discord.Commands | |||
| public IReadOnlyList<PreconditionAttribute> Preconditions { get; } | |||
| internal Module(CommandService service, object instance, ModuleAttribute moduleAttr, TypeInfo typeInfo) | |||
| internal Module(TypeInfo source, CommandService service, object instance, ModuleAttribute moduleAttr) | |||
| { | |||
| Source = source; | |||
| Service = service; | |||
| Name = typeInfo.Name; | |||
| Name = source.Name; | |||
| Instance = instance; | |||
| var summaryAttr = typeInfo.GetCustomAttribute<SummaryAttribute>(); | |||
| var summaryAttr = source.GetCustomAttribute<SummaryAttribute>(); | |||
| if (summaryAttr != null) | |||
| Summary = summaryAttr.Text; | |||
| var descriptionAttr = typeInfo.GetCustomAttribute<DescriptionAttribute>(); | |||
| var descriptionAttr = source.GetCustomAttribute<DescriptionAttribute>(); | |||
| if (descriptionAttr != null) | |||
| Description = descriptionAttr.Text; | |||
| List<Command> commands = new List<Command>(); | |||
| SearchClass(instance, commands, typeInfo, moduleAttr.Prefix ?? ""); | |||
| SearchClass(source, instance, commands, moduleAttr.Prefix ?? ""); | |||
| Commands = commands; | |||
| Preconditions = BuildPreconditions(typeInfo); | |||
| Preconditions = BuildPreconditions(); | |||
| } | |||
| private void SearchClass(object instance, List<Command> commands, TypeInfo typeInfo, string groupPrefix) | |||
| private void SearchClass(TypeInfo parentType, object instance, List<Command> commands, string groupPrefix) | |||
| { | |||
| if (groupPrefix != "") | |||
| groupPrefix += " "; | |||
| foreach (var method in typeInfo.DeclaredMethods) | |||
| foreach (var method in parentType.DeclaredMethods) | |||
| { | |||
| var cmdAttr = method.GetCustomAttribute<CommandAttribute>(); | |||
| if (cmdAttr != null) | |||
| commands.Add(new Command(this, instance, cmdAttr, method, groupPrefix)); | |||
| commands.Add(new Command(method, this, instance, cmdAttr, groupPrefix)); | |||
| } | |||
| foreach (var type in typeInfo.DeclaredNestedTypes) | |||
| foreach (var type in parentType.DeclaredNestedTypes) | |||
| { | |||
| var groupAttrib = type.GetCustomAttribute<GroupAttribute>(); | |||
| if (groupAttrib != null) | |||
| @@ -58,14 +60,14 @@ namespace Discord.Commands | |||
| nextGroupPrefix = groupPrefix + groupAttrib.Prefix ?? type.Name; | |||
| else | |||
| nextGroupPrefix = groupPrefix; | |||
| SearchClass(ReflectionUtils.CreateObject(type, Service), commands, type, nextGroupPrefix); | |||
| SearchClass(type, ReflectionUtils.CreateObject(type, Service), commands, nextGroupPrefix); | |||
| } | |||
| } | |||
| } | |||
| private IReadOnlyList<PreconditionAttribute> BuildPreconditions(TypeInfo typeInfo) | |||
| private IReadOnlyList<PreconditionAttribute> BuildPreconditions() | |||
| { | |||
| return typeInfo.GetCustomAttributes<PreconditionAttribute>().ToImmutableArray(); | |||
| return Source.GetCustomAttributes<PreconditionAttribute>().ToImmutableArray(); | |||
| } | |||
| public override string ToString() => Name; | |||