Add the possibility to register multiple interceptors (#1412)

Having the interceptors registered with the ITypeRegistrar also enables the usage of ITypeResolver in interceptors.
This commit is contained in:
Nils Andresen
2024-01-06 23:28:20 +01:00
committed by GitHub
parent e7ce6a69b7
commit a94bc15746
8 changed files with 147 additions and 7 deletions

View File

@ -229,7 +229,7 @@ public static class ConfiguratorExtensions
throw new ArgumentNullException(nameof(configurator));
}
configurator.Settings.Interceptor = interceptor;
configurator.Settings.Registrar.RegisterInstance<ICommandInterceptor>(interceptor);
return configurator;
}

View File

@ -50,6 +50,7 @@ public interface ICommandAppSettings
/// Gets or sets the <see cref="ICommandInterceptor"/> used
/// to intercept settings before it's being sent to the command.
/// </summary>
[Obsolete("Register the interceptor with the ITypeRegistrar.")]
ICommandInterceptor? Interceptor { get; set; }
/// <summary>

View File

@ -12,5 +12,25 @@ public interface ICommandInterceptor
/// </summary>
/// <param name="context">The intercepted <see cref="CommandContext"/>.</param>
/// <param name="settings">The intercepted <see cref="CommandSettings"/>.</param>
void Intercept(CommandContext context, CommandSettings settings);
void Intercept(CommandContext context, CommandSettings settings)
#if NETSTANDARD2_0
;
#else
{
}
#endif
/// <summary>
/// Intercepts a command result before it's passed as the result.
/// </summary>
/// <param name="context">The intercepted <see cref="CommandContext"/>.</param>
/// <param name="settings">The intercepted <see cref="CommandSettings"/>.</param>
/// <param name="result">The result from the command execution.</param>
void InterceptResult(CommandContext context, CommandSettings settings, ref int result)
#if NETSTANDARD2_0
;
#else
{
}
#endif
}

View File

@ -121,7 +121,7 @@ internal sealed class CommandExecutor
VersionHelper.GetVersion(Assembly.GetEntryAssembly());
}
private static Task<int> Execute(
private static async Task<int> Execute(
CommandTree leaf,
CommandTree tree,
CommandContext context,
@ -130,7 +130,19 @@ internal sealed class CommandExecutor
{
// Bind the command tree against the settings.
var settings = CommandBinder.Bind(tree, leaf.Command.SettingsType, resolver);
configuration.Settings.Interceptor?.Intercept(context, settings);
var interceptors =
((IEnumerable<ICommandInterceptor>?)resolver.Resolve(typeof(IEnumerable<ICommandInterceptor>))
?? Array.Empty<ICommandInterceptor>()).ToList();
#pragma warning disable CS0618 // Type or member is obsolete
if (configuration.Settings.Interceptor != null)
{
interceptors.Add(configuration.Settings.Interceptor);
}
#pragma warning restore CS0618 // Type or member is obsolete
foreach (var interceptor in interceptors)
{
interceptor.Intercept(context, settings);
}
// Create and validate the command.
var command = leaf.CreateCommand(resolver);
@ -141,6 +153,12 @@ internal sealed class CommandExecutor
}
// Execute the command.
return command.Execute(context, settings);
var result = await command.Execute(context, settings);
foreach (var interceptor in interceptors)
{
interceptor.InterceptResult(context, settings, ref result);
}
return result;
}
}

View File

@ -8,6 +8,7 @@ internal sealed class CommandAppSettings : ICommandAppSettings
public int MaximumIndirectExamples { get; set; }
public bool ShowOptionDefaultValues { get; set; }
public IAnsiConsole? Console { get; set; }
[Obsolete("Register the interceptor with the ITypeRegistrar.")]
public ICommandInterceptor? Interceptor { get; set; }
public ITypeRegistrarFrontend Registrar { get; set; }
public CaseSensitivity CaseSensitivity { get; set; }

View File

@ -21,4 +21,11 @@ public sealed class CallbackCommandInterceptor : ICommandInterceptor
{
_callback(context, settings);
}
#if NETSTANDARD2_0
/// <inheritdoc/>
public void InterceptResult(CommandContext context, CommandSettings settings, ref int result)
{
}
#endif
}