From 1965c0539aa7c0a0faa38a447f7eb3ad8705efd2 Mon Sep 17 00:00:00 2001 From: RogueException Date: Fri, 23 Dec 2016 16:03:19 -0400 Subject: [PATCH] Added support for concrete Rest/Socket/RPC classes in command params --- .../Builders/ModuleClassBuilder.cs | 18 ++----- src/Discord.Net.Commands/CommandService.cs | 51 +++++++++++-------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs b/src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs index 7351c7e57..1333edd78 100644 --- a/src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs +++ b/src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs @@ -215,20 +215,6 @@ namespace Discord.Commands else reader = service.GetDefaultTypeReader(paramType); - if (reader == null) - { - var paramTypeInfo = paramType.GetTypeInfo(); - if (paramTypeInfo.IsEnum) - { - reader = EnumTypeReader.GetReader(paramType); - service.AddTypeReader(paramType, reader); - } - else - { - throw new InvalidOperationException($"{paramType.FullName} is not supported as a command parameter, are you missing a TypeReader?"); - } - } - builder.ParameterType = paramType; builder.TypeReader = reader; } @@ -239,10 +225,12 @@ namespace Discord.Commands var readers = service.GetTypeReaders(paramType); TypeReader reader = null; if (readers != null) + { if (readers.TryGetValue(typeReaderType, out reader)) return reader; + } - //could not find any registered type reader: try to create one + //We dont have a cached type reader, create one reader = ReflectionUtils.CreateObject(typeReaderType.GetTypeInfo(), service, DependencyMap.Empty); service.AddTypeReader(paramType, reader); diff --git a/src/Discord.Net.Commands/CommandService.cs b/src/Discord.Net.Commands/CommandService.cs index 7152b87da..18c6c3426 100644 --- a/src/Discord.Net.Commands/CommandService.cs +++ b/src/Discord.Net.Commands/CommandService.cs @@ -17,6 +17,7 @@ namespace Discord.Commands private readonly ConcurrentDictionary _typedModuleDefs; private readonly ConcurrentDictionary> _typeReaders; private readonly ConcurrentDictionary _defaultTypeReaders; + private readonly ImmutableList> _entityTypeReaders; //TODO: Candidate for C#7 Tuple private readonly ConcurrentBag _moduleDefs; private readonly CommandMap _map; @@ -41,27 +42,16 @@ namespace Discord.Commands _map = new CommandMap(this); _typeReaders = new ConcurrentDictionary>(); - _defaultTypeReaders = new ConcurrentDictionary - { - [typeof(IMessage)] = new MessageTypeReader(), - [typeof(IUserMessage)] = new MessageTypeReader(), - [typeof(IChannel)] = new ChannelTypeReader(), - [typeof(IDMChannel)] = new ChannelTypeReader(), - [typeof(IGroupChannel)] = new ChannelTypeReader(), - [typeof(IGuildChannel)] = new ChannelTypeReader(), - [typeof(IMessageChannel)] = new ChannelTypeReader(), - [typeof(IPrivateChannel)] = new ChannelTypeReader(), - [typeof(ITextChannel)] = new ChannelTypeReader(), - [typeof(IVoiceChannel)] = new ChannelTypeReader(), - - [typeof(IRole)] = new RoleTypeReader(), - - [typeof(IUser)] = new UserTypeReader(), - [typeof(IGroupUser)] = new UserTypeReader(), - [typeof(IGuildUser)] = new UserTypeReader(), - }; + _defaultTypeReaders = new ConcurrentDictionary(); foreach (var type in PrimitiveParsers.SupportedTypes) _defaultTypeReaders[type] = PrimitiveTypeReader.Create(type); + + var entityTypeReaders = ImmutableList.CreateBuilder>(); + entityTypeReaders.Add(new Tuple(typeof(IMessage), typeof(MessageTypeReader<>))); + entityTypeReaders.Add(new Tuple(typeof(IChannel), typeof(ChannelTypeReader<>))); + entityTypeReaders.Add(new Tuple(typeof(IRole), typeof(RoleTypeReader<>))); + entityTypeReaders.Add(new Tuple(typeof(IUser), typeof(UserTypeReader<>))); + _entityTypeReaders = entityTypeReaders.ToImmutable(); } //Modules @@ -208,11 +198,32 @@ namespace Discord.Commands TypeReader reader; if (_defaultTypeReaders.TryGetValue(type, out reader)) return reader; + var typeInfo = type.GetTypeInfo(); + + //Is this an enum? + if (typeInfo.IsEnum) + { + reader = EnumTypeReader.GetReader(type); + _defaultTypeReaders[type] = reader; + return reader; + } + + //Is this an entity? + for (int i = 0; i < _entityTypeReaders.Count; i++) + { + if (type == _entityTypeReaders[i].Item1 || typeInfo.ImplementedInterfaces.Contains(_entityTypeReaders[i].Item1)) + { + reader = Activator.CreateInstance(_entityTypeReaders[i].Item2.MakeGenericType(type)) as TypeReader; + _defaultTypeReaders[type] = reader; + return reader; + } + } return null; } //Execution - public SearchResult Search(CommandContext context, int argPos) => Search(context, context.Message.Content.Substring(argPos)); + public SearchResult Search(CommandContext context, int argPos) + => Search(context, context.Message.Content.Substring(argPos)); public SearchResult Search(CommandContext context, string input) { string searchInput = _caseSensitive ? input : input.ToLowerInvariant();