Browse Source

Added support for concrete Rest/Socket/RPC classes in command params

tags/1.0-rc
RogueException 8 years ago
parent
commit
1965c0539a
2 changed files with 34 additions and 35 deletions
  1. +3
    -15
      src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs
  2. +31
    -20
      src/Discord.Net.Commands/CommandService.cs

+ 3
- 15
src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs View File

@@ -215,20 +215,6 @@ namespace Discord.Commands
else else
reader = service.GetDefaultTypeReader(paramType); 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.ParameterType = paramType;
builder.TypeReader = reader; builder.TypeReader = reader;
} }
@@ -239,10 +225,12 @@ namespace Discord.Commands
var readers = service.GetTypeReaders(paramType); var readers = service.GetTypeReaders(paramType);
TypeReader reader = null; TypeReader reader = null;
if (readers != null) if (readers != null)
{
if (readers.TryGetValue(typeReaderType, out reader)) if (readers.TryGetValue(typeReaderType, out reader))
return 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<TypeReader>(typeReaderType.GetTypeInfo(), service, DependencyMap.Empty); reader = ReflectionUtils.CreateObject<TypeReader>(typeReaderType.GetTypeInfo(), service, DependencyMap.Empty);
service.AddTypeReader(paramType, reader); service.AddTypeReader(paramType, reader);




+ 31
- 20
src/Discord.Net.Commands/CommandService.cs View File

@@ -17,6 +17,7 @@ namespace Discord.Commands
private readonly ConcurrentDictionary<Type, ModuleInfo> _typedModuleDefs; private readonly ConcurrentDictionary<Type, ModuleInfo> _typedModuleDefs;
private readonly ConcurrentDictionary<Type, ConcurrentDictionary<Type, TypeReader>> _typeReaders; private readonly ConcurrentDictionary<Type, ConcurrentDictionary<Type, TypeReader>> _typeReaders;
private readonly ConcurrentDictionary<Type, TypeReader> _defaultTypeReaders; private readonly ConcurrentDictionary<Type, TypeReader> _defaultTypeReaders;
private readonly ImmutableList<Tuple<Type, Type>> _entityTypeReaders; //TODO: Candidate for C#7 Tuple
private readonly ConcurrentBag<ModuleInfo> _moduleDefs; private readonly ConcurrentBag<ModuleInfo> _moduleDefs;
private readonly CommandMap _map; private readonly CommandMap _map;


@@ -41,27 +42,16 @@ namespace Discord.Commands
_map = new CommandMap(this); _map = new CommandMap(this);
_typeReaders = new ConcurrentDictionary<Type, ConcurrentDictionary<Type, TypeReader>>(); _typeReaders = new ConcurrentDictionary<Type, ConcurrentDictionary<Type, TypeReader>>();


_defaultTypeReaders = new ConcurrentDictionary<Type, TypeReader>
{
[typeof(IMessage)] = new MessageTypeReader<IMessage>(),
[typeof(IUserMessage)] = new MessageTypeReader<IUserMessage>(),
[typeof(IChannel)] = new ChannelTypeReader<IChannel>(),
[typeof(IDMChannel)] = new ChannelTypeReader<IDMChannel>(),
[typeof(IGroupChannel)] = new ChannelTypeReader<IGroupChannel>(),
[typeof(IGuildChannel)] = new ChannelTypeReader<IGuildChannel>(),
[typeof(IMessageChannel)] = new ChannelTypeReader<IMessageChannel>(),
[typeof(IPrivateChannel)] = new ChannelTypeReader<IPrivateChannel>(),
[typeof(ITextChannel)] = new ChannelTypeReader<ITextChannel>(),
[typeof(IVoiceChannel)] = new ChannelTypeReader<IVoiceChannel>(),

[typeof(IRole)] = new RoleTypeReader<IRole>(),

[typeof(IUser)] = new UserTypeReader<IUser>(),
[typeof(IGroupUser)] = new UserTypeReader<IGroupUser>(),
[typeof(IGuildUser)] = new UserTypeReader<IGuildUser>(),
};
_defaultTypeReaders = new ConcurrentDictionary<Type, TypeReader>();
foreach (var type in PrimitiveParsers.SupportedTypes) foreach (var type in PrimitiveParsers.SupportedTypes)
_defaultTypeReaders[type] = PrimitiveTypeReader.Create(type); _defaultTypeReaders[type] = PrimitiveTypeReader.Create(type);

var entityTypeReaders = ImmutableList.CreateBuilder<Tuple<Type, Type>>();
entityTypeReaders.Add(new Tuple<Type, Type>(typeof(IMessage), typeof(MessageTypeReader<>)));
entityTypeReaders.Add(new Tuple<Type, Type>(typeof(IChannel), typeof(ChannelTypeReader<>)));
entityTypeReaders.Add(new Tuple<Type, Type>(typeof(IRole), typeof(RoleTypeReader<>)));
entityTypeReaders.Add(new Tuple<Type, Type>(typeof(IUser), typeof(UserTypeReader<>)));
_entityTypeReaders = entityTypeReaders.ToImmutable();
} }


//Modules //Modules
@@ -208,11 +198,32 @@ namespace Discord.Commands
TypeReader reader; TypeReader reader;
if (_defaultTypeReaders.TryGetValue(type, out reader)) if (_defaultTypeReaders.TryGetValue(type, out reader))
return 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; return null;
} }


//Execution //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) public SearchResult Search(CommandContext context, string input)
{ {
string searchInput = _caseSensitive ? input : input.ToLowerInvariant(); string searchInput = _caseSensitive ? input : input.ToLowerInvariant();


Loading…
Cancel
Save