| File: CliTransaction.cs | Web Access |
| Project: src\sdk\src\Cli\dotnet\dotnet.csproj (dotnet) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable disable namespace Microsoft.DotNet.Cli; internal interface ITransactionContext { public void AddRollbackAction(Action action); // Add an action which will be run at the end of the transaction, whether it succeeds or not (after any rollback actions, if applicable) public void AddCleanupAction(Action action); } internal class CliTransaction { // Delegate called when rollback starts, mainly in order to print a log message public Action RollbackStarted { get; set; } // Delegate called when rollback fails. If set, exception will be passed to the delegate, but not rethrown public Action<Exception> RollbackFailed { get; set; } public static void RunNew(Action<ITransactionContext> action) { new CliTransaction().Run(action); } public void Run(Action<ITransactionContext> action, Action rollback) { Run(context => { context.AddRollbackAction(rollback); action(context); }); } public void Run(Action<ITransactionContext> action) { TransactionContext transactionContext = new(); try { action(transactionContext); } catch (Exception) { // Roll back transaction RollbackStarted?.Invoke(); transactionContext.RollbackActions.Reverse(); foreach (var rollbackAction in transactionContext.RollbackActions) { try { rollbackAction(); } catch (Exception ex) { if (RollbackFailed != null) { RollbackFailed(ex); } else { throw; } } } throw; } finally { foreach (var cleanupAction in transactionContext.CleanupActions) { cleanupAction(); } } } class TransactionContext : ITransactionContext { public List<Action> RollbackActions { get; set; } = []; // Actions which will be run either when the transaction completes successfully, or after rollback actions have been run public List<Action> CleanupActions { get; set; } = []; public void AddRollbackAction(Action action) { RollbackActions.Add(action); } public void AddCleanupAction(Action action) { CleanupActions.Add(action); } } } static class CliTransactionExtensions { public static void Run(this ITransactionContext context, Action action, Action rollback = null, Action cleanup = null) { if (rollback != null) { context.AddRollbackAction(rollback); } if (cleanup != null) { context.AddCleanupAction(cleanup); } action(); } }