Browse Source

Improve parameter precondition type safety

Also removes some terrible code which was left over when I first
implemented parameter preconditions. I don't know why that was there.

With this commit, parameter preconditions should be much safer as they
use generic methods instead of janky casting of objects.
pull/532/head
FiniteReality 8 years ago
parent
commit
c481966923
3 changed files with 17 additions and 10 deletions
  1. +1
    -1
      src/Discord.Net.Commands/Attributes/ParameterPreconditionAttribute.cs
  2. +4
    -2
      src/Discord.Net.Commands/Info/CommandInfo.cs
  3. +12
    -7
      src/Discord.Net.Commands/Info/ParameterInfo.cs

+ 1
- 1
src/Discord.Net.Commands/Attributes/ParameterPreconditionAttribute.cs View File

@@ -6,6 +6,6 @@ namespace Discord.Commands
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)] [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)]
public abstract class ParameterPreconditionAttribute : Attribute public abstract class ParameterPreconditionAttribute : Attribute
{ {
public abstract Task<PreconditionResult> CheckPermissions(ICommandContext context, ParameterInfo parameter, object value, IDependencyMap map);
public abstract Task<PreconditionResult> CheckPermissions<T>(ICommandContext context, ParameterInfo parameter, T value, IDependencyMap map);
} }
} }

+ 4
- 2
src/Discord.Net.Commands/Info/CommandInfo.cs View File

@@ -128,9 +128,11 @@ namespace Discord.Commands
{ {
object[] args = GenerateArgs(argList, paramList); object[] args = GenerateArgs(argList, paramList);


foreach (var parameter in Parameters)
for (int position = 0; position < Parameters.Count; position++)
{ {
var result = await parameter.CheckPreconditionsAsync(context, args, map).ConfigureAwait(false);
var parameter = Parameters[position];
var argument = args[position];
var result = await parameter.CheckPreconditionsAsync(context, argument, map).ConfigureAwait(false);
if (!result.IsSuccess) if (!result.IsSuccess)
return ExecuteResult.FromError(result); return ExecuteResult.FromError(result);
} }


+ 12
- 7
src/Discord.Net.Commands/Info/ParameterInfo.cs View File

@@ -4,12 +4,18 @@ using System.Collections.Immutable;
using System.Threading.Tasks; using System.Threading.Tasks;


using Discord.Commands.Builders; using Discord.Commands.Builders;
using System.Reflection;


namespace Discord.Commands namespace Discord.Commands
{ {
public class ParameterInfo public class ParameterInfo
{ {

private static MethodInfo _checkPermissionsMethod = typeof(ParameterPreconditionAttribute)
.GetTypeInfo().GetDeclaredMethod("CheckPermissions");

private readonly TypeReader _reader; private readonly TypeReader _reader;
private readonly MethodInfo _specializedCheckPermissionsMethod;


public CommandInfo Command { get; } public CommandInfo Command { get; }
public string Name { get; } public string Name { get; }
@@ -38,21 +44,20 @@ namespace Discord.Commands
Preconditions = builder.Preconditions.ToImmutableArray(); Preconditions = builder.Preconditions.ToImmutableArray();


_reader = builder.TypeReader; _reader = builder.TypeReader;

_specializedCheckPermissionsMethod = _checkPermissionsMethod.MakeGenericMethod(Type);
} }


public async Task<PreconditionResult> CheckPreconditionsAsync(ICommandContext context, object[] args, IDependencyMap map = null)
public async Task<PreconditionResult> CheckPreconditionsAsync(ICommandContext context, object arg, IDependencyMap map = null)
{ {
if (map == null) if (map == null)
map = DependencyMap.Empty; map = DependencyMap.Empty;


int position = 0;
for(position = 0; position < Command.Parameters.Count; position++)
if (Command.Parameters[position] == this)
break;

foreach (var precondition in Preconditions) foreach (var precondition in Preconditions)
{ {
var result = await precondition.CheckPermissions(context, this, args[position], map).ConfigureAwait(false);
object[] parameters = new []{ context, this, arg, map };
var resultTask = (_specializedCheckPermissionsMethod.Invoke(precondition, parameters) as Task<PreconditionResult>);
var result = await resultTask.ConfigureAwait(false);
if (!result.IsSuccess) if (!result.IsSuccess)
return result; return result;
} }


Loading…
Cancel
Save