-
-
Notifications
You must be signed in to change notification settings - Fork 526
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
208 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
namespace Spectre.Console.Cli; | ||
#pragma warning restore S2326 | ||
|
||
/// <summary> | ||
/// Represents the args for a command exception. | ||
/// </summary> | ||
public readonly struct CommandExceptionArgs | ||
{ | ||
/// <summary> | ||
/// Gets the command context. | ||
/// </summary> | ||
public CommandContext Context { get; } | ||
|
||
/// <summary> | ||
/// Gets the exception that was thrown. | ||
/// </summary> | ||
public Exception Exception { get; } | ||
|
||
/// <summary> | ||
/// Gets the command type. | ||
/// </summary> | ||
public Type? CommandType { get; } | ||
|
||
internal CommandExceptionArgs(CommandContext context, Exception exception, Type? commandType) | ||
{ | ||
Context = context; | ||
Exception = exception; | ||
CommandType = commandType; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
namespace Spectre.Console.Cli; | ||
|
||
/// <summary> | ||
/// Represents an args handler. | ||
/// Exception handlers are used to handle exceptions that occur during command execution. | ||
/// </summary> | ||
public interface ICommandExceptionHandler | ||
{ | ||
/// <summary> | ||
/// Handles the specified args. | ||
/// </summary> | ||
/// <param name="args">The args to handle.</param> | ||
/// <returns><c>true</c> if the args was handled, otherwise <c>false</c>.</returns> | ||
bool Handle(CommandExceptionArgs args); | ||
} | ||
|
||
/// <summary> | ||
/// Represents an args handler for a specific command. | ||
/// </summary> | ||
/// <typeparam name="TCommand">Type of the command.</typeparam> | ||
// ReSharper disable once UnusedTypeParameter | ||
#pragma warning disable S2326 | ||
public interface ICommandExceptionHandler<TCommand> : ICommandExceptionHandler | ||
where TCommand : ICommand | ||
{ | ||
} |
75 changes: 75 additions & 0 deletions
75
src/Spectre.Console.Cli/Internal/CommandExceptionHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
using Spectre.Console.Cli.Internal.Extensions; | ||
|
||
namespace Spectre.Console.Cli.Internal; | ||
|
||
internal static class CommandExceptionHandler | ||
{ | ||
public static bool HandleException( | ||
CommandTree leaf, | ||
CommandContext context, | ||
ITypeResolver resolver, | ||
Exception ex) | ||
{ | ||
var args = new CommandExceptionArgs(context, ex, leaf?.Command?.CommandType); | ||
|
||
if (leaf?.Command?.CommandType == null) | ||
{ | ||
return TryInvokeHandler( | ||
resolver, | ||
args, | ||
typeof(IEnumerable<ICommandExceptionHandler>), | ||
typeof(ICommandExceptionHandler)); | ||
} | ||
|
||
var handlerType = typeof(ICommandExceptionHandler<>) | ||
.MakeGenericType(leaf.Command.CommandType); | ||
|
||
var enumerableHandlerType = typeof(IEnumerable<>) | ||
.MakeGenericType(handlerType); | ||
|
||
var handled = TryInvokeHandler(resolver, args, enumerableHandlerType, handlerType); | ||
if (handled) | ||
{ | ||
return true; | ||
} | ||
|
||
return TryInvokeHandler(resolver, args, typeof(IEnumerable<ICommandExceptionHandler>), | ||
typeof(ICommandExceptionHandler)); | ||
} | ||
|
||
private static bool TryInvokeHandler( | ||
ITypeResolver resolver, | ||
CommandExceptionArgs args, | ||
Type enumerableHandlerType, | ||
Type handlerType) | ||
{ | ||
var handlers = resolver.TryResolve(enumerableHandlerType); | ||
if (handlers is IEnumerable<ICommandExceptionHandler> exHandlerEnumerable) | ||
{ | ||
foreach (var exHandlerItem in exHandlerEnumerable) | ||
{ | ||
var isHandled = exHandlerItem.Handle(args); | ||
if (isHandled) | ||
{ | ||
return true; | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
var handler = resolver.TryResolve(handlerType); | ||
if (handler is not ICommandExceptionHandler exHandler) | ||
{ | ||
return false; | ||
} | ||
|
||
var isHandled = exHandler.Handle(args); | ||
if (isHandled) | ||
{ | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
src/Spectre.Console.Cli/Internal/Extensions/TypeResolverExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
namespace Spectre.Console.Cli.Internal.Extensions; | ||
|
||
internal static class TypeResolverExtensions | ||
{ | ||
public static object? TryResolve(this ITypeResolver resolver, Type type) | ||
{ | ||
if (resolver == null) | ||
{ | ||
throw new ArgumentNullException(nameof(resolver)); | ||
} | ||
|
||
if (type == null) | ||
{ | ||
throw new ArgumentNullException(nameof(type)); | ||
} | ||
|
||
if (resolver is TypeResolverAdapter adapter) | ||
{ | ||
return adapter.TryResolve(type); | ||
} | ||
|
||
try | ||
{ | ||
return resolver.Resolve(type); | ||
} | ||
catch (Exception) | ||
{ | ||
return null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters