private async Task <IArgumentParserResult> ParseCommandAsync(CommandContext context, ICommand command, string rawArgs) { var provider = context.CommandServices; IArgumentParser argumentParser; var argumentParserType = command.GetArgumentParserType(); if (argumentParserType.HasContent()) { argumentParser = provider.GetService(argumentParserType) as IArgumentParser; if (argumentParser.HasNoContent()) { argumentParser = ActivatorUtilities.CreateInstance(provider, argumentParserType) as IArgumentParser; MiddlewareUtils.RegisterForDispose(argumentParser, context); } } else { argumentParser = provider.GetRequiredService <IArgumentParser>(); } return(await argumentParser.ParseAsync(context, command, rawArgs)); }
private async Task ParseCommandFromMatchesAsync(CommandContext context, CommandDelegate next) { context.Features.Set <IArgumentParserFeature>(new ArgumentParserFeature()); var matchesFeature = context.Features.Get <ICommandMatchesFeature>(); var argumentParserFeature = context.Features.Get <IArgumentParserFeature>(); if (matchesFeature.HasNoContent() || matchesFeature.CommandMatches.HasNoContent()) { throw new InvalidOperationException($"Can't get command matches from feature: {nameof(ICommandMatchesFeature)}."); } var bestMatches = new List <ICommandMatch>(); var fails = new Dictionary <ICommand, IResult>(); foreach (var match in matchesFeature.CommandMatches) { var result = await ParseCommandAsync(context, match.Command, match.RemainingInput); if (result.Success) { bestMatches.Add(match); argumentParserFeature.CommandArgs.Add(match, result.Args.Values.ToArray()); } else { fails.Add(match.Command, result); } } if (bestMatches.HasNoContent()) { _logger.LogInformation("All matched commands returned fail for command parsing."); context.Result = MiddlewareUtils.GetErrorResult(fails); return; } var config = context.CommandServices.GetRequiredService <IOptions <MariCommandsOptions> >().Value; if (!config.ContinueMultiMatchAfterParser) { bestMatches = bestMatches .OrderByDescending(a => a.Command.Priority) .Take(1) .ToList(); var bestMatch = bestMatches.FirstOrDefault(); context.Command = bestMatch.Command; context.Alias = bestMatch.Alias; context.Args = argumentParserFeature.CommandArgs[bestMatch].ToList(); } matchesFeature.CommandMatches = bestMatches; await next(context); }
private ITypeParser GetTypeParser(CommandContext context, IParameter param) { var typeParserType = param.TypeParserType; if (typeParserType.HasContent()) { var typeParser = context.CommandServices.GetService(typeParserType) as ITypeParser; if (typeParser.HasNoContent()) { typeParser = ActivatorUtilities.CreateInstance(context.CommandServices, typeParserType) as ITypeParser; MiddlewareUtils.RegisterForDispose(typeParser, context); } return(typeParser); } var typeParserProvider = context.CommandServices.GetRequiredService <ITypeParserProvider>(); var parameterType = param.IsParams ? param.ParameterInfo.ParameterType.GetElementType() : param.ParameterInfo.ParameterType; return(typeParserProvider.GetTypeParser(parameterType)); }
private object GetModule(CommandContext context, ICommand command) { var module = command.Module.Invoker.CreateInstance(context.CommandServices); MiddlewareUtils.RegisterForDispose(module, context); return(module); }
/// <summary> /// Add a middleware type to the command request pipeline. /// </summary> /// <param name="app">The current command aplication builder.</param> /// <param name="middlewareArgs">Additional ctor args for this middleware.</param> /// <returns>The current command aplication builder.</returns> public static ICommandApplicationBuilder UseMiddleware <TMiddleware>(this ICommandApplicationBuilder app, params object[] middlewareArgs) where TMiddleware : ICommandMiddleware { app.Use((next) => { var types = middlewareArgs ?.Select(a => a.GetType()) ?.ToArray() ?? new Type[0]; var instanceFactory = ActivatorUtilities.CreateFactory(typeof(TMiddleware), types ?? Type.EmptyTypes); return(async context => { var instance = instanceFactory(context.CommandServices, middlewareArgs); await(instance as ICommandMiddleware).InvokeAsync(context, next); await MiddlewareUtils.SwitchDisposeAsync(instance); }); }); return(app); }
public async Task InvokeAsync(CommandContext context, CommandDelegate next) { context.NotNull(nameof(context)); if (context.Result.HasContent()) { await next(context); return; } var isUniqueCommand = context.Command.HasContent() && context.Args != null; if (isUniqueCommand) { var result = await ExecutePreconditionsForContextAsync(context); if (result.Success) { await next(context); } else { context.Result = result; } return; } var matchesFeature = context.Features.Get <ICommandMatchesFeature>(); if (matchesFeature.HasNoContent() || matchesFeature.CommandMatches.HasNoContent()) { throw new InvalidOperationException($"Can't get command matches from feature: {nameof(ICommandMatchesFeature)}."); } var argumentParserFeature = context.Features.Get <IArgumentParserFeature>(); if (argumentParserFeature.HasNoContent() || argumentParserFeature.CommandArgs.HasNoContent()) { throw new InvalidOperationException($"Can't get command matches parsed param values from feature: {nameof(IArgumentParserFeature)}."); } var matches = matchesFeature.CommandMatches; var parsedArgs = argumentParserFeature.CommandArgs; var fails = new Dictionary <ICommand, IResult>(); var bestMatches = new List <ICommandMatch>(); foreach (var match in matches) { var command = match.Command; var args = parsedArgs[match]; var result = await ExecutePreconditionsAsync(command, args, context); if (result.Success) { bestMatches.Add(match); } else { fails.Add(command, result); } } if (bestMatches.HasNoContent()) { _logger.LogInformation("All matched commands returned fail for input count."); context.Result = MiddlewareUtils.GetErrorResult(fails); return; } matchesFeature.CommandMatches = bestMatches; await next(context); }
public async Task InvokeAsync(CommandContext context, CommandDelegate next) { context.NotNull(nameof(context)); if (context.Result.HasContent() || context.Args != null) { await next(context); return; } var verifyCommandInputCount = context.Command.HasContent() && !string.IsNullOrWhiteSpace(context.RawArgs); if (verifyCommandInputCount) { context.Features.Set <ICommandMatchesFeature>(new CommandMatchesFeature { CommandMatches = new List <ICommandMatch> { new CommandMatch(context.Command, null, null, context.RawArgs) } }); } var matchesFeature = context.Features.Get <ICommandMatchesFeature>(); if (matchesFeature.HasNoContent() || matchesFeature.CommandMatches.HasNoContent()) { throw new InvalidOperationException($"Can't get command matches from feature: {nameof(ICommandMatchesFeature)}."); } var multiMatches = new List <ICommandMatch>(); if (matchesFeature.CommandMatches.Count > 1) { multiMatches = matchesFeature.CommandMatches .Where(a => a.Command.Module.GetMatchHandling(_config) == MultiMatchHandling.Best) .ToList(); } else { multiMatches = matchesFeature.CommandMatches.ToList(); } if (multiMatches.HasNoContent()) { _logger.LogInformation($"This input has more than one match but none of then has {MultiMatchHandling.Best} as configuration."); context.Result = MultiMatchErrorResult.FromMatches(matchesFeature.CommandMatches); return; } matchesFeature.CommandMatches = multiMatches; var bestMatches = new List <ICommandMatch>(); var fails = new Dictionary <ICommand, IResult>(); foreach (var match in matchesFeature.CommandMatches) { var inputCount = string.IsNullOrWhiteSpace(match.RemainingInput) ? 0 : match.RemainingInput.Split(_config.Separator).Count(); var command = match.Command; if (command.Parameters.Count > inputCount) { var hasAnyOptional = command.Parameters.Any(a => IsOptional(a)); if (!hasAnyOptional) { fails.Add(command, BadArgCountResult.FromCommand(command)); continue; } var optionalsCount = command.Parameters.Count(a => IsOptional(a)); var missingCount = command.Parameters.Count - inputCount; if (optionalsCount < missingCount) { fails.Add(command, BadArgCountResult.FromCommand(command)); continue; } } else if (command.Parameters.Count < inputCount) { var ignoreExtraArgs = command.GetIgnoreExtraArgs(_config); if (!ignoreExtraArgs) { fails.Add(command, BadArgCountResult.FromCommand(command)); continue; } } bestMatches.Add(match); } if (bestMatches.HasNoContent()) { _logger.LogInformation("All matched commands returned fail for input count."); context.Result = MiddlewareUtils.GetErrorResult(fails); return; } matchesFeature.CommandMatches = bestMatches; await next(context); }