Browse Source

Don't create a service scope in CommandService#ExecuteAsync anymore

IServiceProvider does not support scopes by itself - this is a behavior
introduced by Microsoft's DI container. As such, not all DI containers
may support an IScopeFactory the way that Microsoft's DI is expecting
them to.

This also means that our builtin EmptyServiceProvider does not support
scopes - meaning that users who do not use a DI container can not invoke
commands.
tags/2.0
Christopher F 7 years ago
parent
commit
f9ac190e9a
1 changed files with 66 additions and 68 deletions
  1. +66
    -68
      src/Discord.Net.Commands/CommandService.cs

+ 66
- 68
src/Discord.Net.Commands/CommandService.cs View File

@@ -283,94 +283,92 @@ namespace Discord.Commands
public async Task<IResult> ExecuteAsync(ICommandContext context, string input, IServiceProvider services = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
{
services = services ?? EmptyServiceProvider.Instance;
using (var scope = services.CreateScope())
{
var searchResult = Search(context, input);
if (!searchResult.IsSuccess)
return searchResult;

var commands = searchResult.Commands;
var preconditionResults = new Dictionary<CommandMatch, PreconditionResult>();
var searchResult = Search(context, input);
if (!searchResult.IsSuccess)
return searchResult;

foreach (var match in commands)
{
preconditionResults[match] = await match.Command.CheckPreconditionsAsync(context, scope.ServiceProvider).ConfigureAwait(false);
}
var commands = searchResult.Commands;
var preconditionResults = new Dictionary<CommandMatch, PreconditionResult>();

var successfulPreconditions = preconditionResults
.Where(x => x.Value.IsSuccess)
.ToArray();
foreach (var match in commands)
{
preconditionResults[match] = await match.Command.CheckPreconditionsAsync(context, services).ConfigureAwait(false);
}

if (successfulPreconditions.Length == 0)
{
//All preconditions failed, return the one from the highest priority command
var bestCandidate = preconditionResults
.OrderByDescending(x => x.Key.Command.Priority)
.FirstOrDefault(x => !x.Value.IsSuccess);
return bestCandidate.Value;
}
var successfulPreconditions = preconditionResults
.Where(x => x.Value.IsSuccess)
.ToArray();

//If we get this far, at least one precondition was successful.
if (successfulPreconditions.Length == 0)
{
//All preconditions failed, return the one from the highest priority command
var bestCandidate = preconditionResults
.OrderByDescending(x => x.Key.Command.Priority)
.FirstOrDefault(x => !x.Value.IsSuccess);
return bestCandidate.Value;
}

var parseResultsDict = new Dictionary<CommandMatch, ParseResult>();
foreach (var pair in successfulPreconditions)
{
var parseResult = await pair.Key.ParseAsync(context, searchResult, pair.Value, scope.ServiceProvider).ConfigureAwait(false);
//If we get this far, at least one precondition was successful.

if (parseResult.Error == CommandError.MultipleMatches)
var parseResultsDict = new Dictionary<CommandMatch, ParseResult>();
foreach (var pair in successfulPreconditions)
{
var parseResult = await pair.Key.ParseAsync(context, searchResult, pair.Value, services).ConfigureAwait(false);

if (parseResult.Error == CommandError.MultipleMatches)
{
IReadOnlyList<TypeReaderValue> argList, paramList;
switch (multiMatchHandling)
{
IReadOnlyList<TypeReaderValue> argList, paramList;
switch (multiMatchHandling)
{
case MultiMatchHandling.Best:
argList = parseResult.ArgValues.Select(x => x.Values.OrderByDescending(y => y.Score).First()).ToImmutableArray();
paramList = parseResult.ParamValues.Select(x => x.Values.OrderByDescending(y => y.Score).First()).ToImmutableArray();
parseResult = ParseResult.FromSuccess(argList, paramList);
break;
}
case MultiMatchHandling.Best:
argList = parseResult.ArgValues.Select(x => x.Values.OrderByDescending(y => y.Score).First()).ToImmutableArray();
paramList = parseResult.ParamValues.Select(x => x.Values.OrderByDescending(y => y.Score).First()).ToImmutableArray();
parseResult = ParseResult.FromSuccess(argList, paramList);
break;
}

parseResultsDict[pair.Key] = parseResult;
}

// Calculates the 'score' of a command given a parse result
float CalculateScore(CommandMatch match, ParseResult parseResult)
{
float argValuesScore = 0, paramValuesScore = 0;
parseResultsDict[pair.Key] = parseResult;
}

if (match.Command.Parameters.Count > 0)
{
var argValuesSum = parseResult.ArgValues?.Sum(x => x.Values.OrderByDescending(y => y.Score).FirstOrDefault().Score) ?? 0;
var paramValuesSum = parseResult.ParamValues?.Sum(x => x.Values.OrderByDescending(y => y.Score).FirstOrDefault().Score) ?? 0;
// Calculates the 'score' of a command given a parse result
float CalculateScore(CommandMatch match, ParseResult parseResult)
{
float argValuesScore = 0, paramValuesScore = 0;

argValuesScore = argValuesSum / match.Command.Parameters.Count;
paramValuesScore = paramValuesSum / match.Command.Parameters.Count;
}
if (match.Command.Parameters.Count > 0)
{
var argValuesSum = parseResult.ArgValues?.Sum(x => x.Values.OrderByDescending(y => y.Score).FirstOrDefault().Score) ?? 0;
var paramValuesSum = parseResult.ParamValues?.Sum(x => x.Values.OrderByDescending(y => y.Score).FirstOrDefault().Score) ?? 0;

var totalArgsScore = (argValuesScore + paramValuesScore) / 2;
return match.Command.Priority + totalArgsScore * 0.99f;
argValuesScore = argValuesSum / match.Command.Parameters.Count;
paramValuesScore = paramValuesSum / match.Command.Parameters.Count;
}

//Order the parse results by their score so that we choose the most likely result to execute
var parseResults = parseResultsDict
.OrderByDescending(x => CalculateScore(x.Key, x.Value));
var totalArgsScore = (argValuesScore + paramValuesScore) / 2;
return match.Command.Priority + totalArgsScore * 0.99f;
}

var successfulParses = parseResults
.Where(x => x.Value.IsSuccess)
.ToArray();
//Order the parse results by their score so that we choose the most likely result to execute
var parseResults = parseResultsDict
.OrderByDescending(x => CalculateScore(x.Key, x.Value));

if (successfulParses.Length == 0)
{
//All parses failed, return the one from the highest priority command, using score as a tie breaker
var bestMatch = parseResults
.FirstOrDefault(x => !x.Value.IsSuccess);
return bestMatch.Value;
}
var successfulParses = parseResults
.Where(x => x.Value.IsSuccess)
.ToArray();

//If we get this far, at least one parse was successful. Execute the most likely overload.
var chosenOverload = successfulParses[0];
return await chosenOverload.Key.ExecuteAsync(context, chosenOverload.Value, scope.ServiceProvider).ConfigureAwait(false);
if (successfulParses.Length == 0)
{
//All parses failed, return the one from the highest priority command, using score as a tie breaker
var bestMatch = parseResults
.FirstOrDefault(x => !x.Value.IsSuccess);
return bestMatch.Value;
}

//If we get this far, at least one parse was successful. Execute the most likely overload.
var chosenOverload = successfulParses[0];
return await chosenOverload.Key.ExecuteAsync(context, chosenOverload.Value, services).ConfigureAwait(false);
}
}
}

Loading…
Cancel
Save