Ionite
1 year ago
4 changed files with 102 additions and 3 deletions
@ -0,0 +1,76 @@
|
||||
using System; |
||||
using System.Diagnostics.CodeAnalysis; |
||||
using CommunityToolkit.Mvvm.Input; |
||||
using NLog; |
||||
using StabilityMatrix.Avalonia.Services; |
||||
using StabilityMatrix.Core.Extensions; |
||||
|
||||
namespace StabilityMatrix.Avalonia.Extensions; |
||||
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] |
||||
public static class RelayCommandExtensions |
||||
{ |
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); |
||||
|
||||
/// <summary> |
||||
/// Attach an error handler to the command that will invoke the given action when an exception occurs. |
||||
/// </summary> |
||||
/// <param name="command">The command to attach the error handler to.</param> |
||||
/// <param name="onError">The action to invoke when an exception occurs.</param> |
||||
/// <exception cref="ArgumentException">Thrown if the command was not created with the FlowExceptionsToTaskScheduler option enabled.</exception> |
||||
public static T WithErrorHandler<T>(this T command, Action<Exception> onError) where T : IAsyncRelayCommand |
||||
{ |
||||
if (command is AsyncRelayCommand relayCommand) |
||||
{ |
||||
// Check that the FlowExceptionsToTaskScheduler flag is set |
||||
var options = relayCommand.GetPrivateField<AsyncRelayCommandOptions>("options"); |
||||
|
||||
if (!options.HasFlag(AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler)) |
||||
{ |
||||
throw new ArgumentException( |
||||
"The command must be created with the FlowExceptionsToTaskScheduler option enabled" |
||||
); |
||||
} |
||||
} |
||||
|
||||
command.PropertyChanged += (sender, e) => |
||||
{ |
||||
if (sender is not IAsyncRelayCommand senderCommand) |
||||
{ |
||||
return; |
||||
} |
||||
// On ExecutionTask updates, check if there is an exception |
||||
if ( |
||||
e.PropertyName == nameof(AsyncRelayCommand.ExecutionTask) |
||||
&& senderCommand.ExecutionTask is { Exception: { } exception } |
||||
) |
||||
{ |
||||
onError(exception); |
||||
} |
||||
}; |
||||
|
||||
return command; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Attach an error handler to the command that will log the error and show a notification. |
||||
/// </summary> |
||||
/// <param name="command">The command to attach the error handler to.</param> |
||||
/// <param name="notificationService">The notification service to use to show the notification.</param> |
||||
/// <param name="logLevel">The log level to use when logging the error. Defaults to LogLevel.Error</param> |
||||
/// <exception cref="ArgumentException">Thrown if the command was not created with the FlowExceptionsToTaskScheduler option enabled.</exception> |
||||
public static T WithNotificationErrorHandler<T>( |
||||
this T command, |
||||
INotificationService notificationService, |
||||
LogLevel? logLevel = default |
||||
) where T : IAsyncRelayCommand |
||||
{ |
||||
logLevel ??= LogLevel.Error; |
||||
|
||||
return command.WithErrorHandler(e => |
||||
{ |
||||
Logger.Log(logLevel, e, "Error executing command"); |
||||
notificationService.ShowPersistent("Error", $"[{e.GetType().Name}] {e.Message}"); |
||||
}); |
||||
} |
||||
} |
Loading…
Reference in new issue