< Summary

Information
Class: Gravitas.Support.LifecycleHookHandler
Assembly: Gravitas
File(s): /home/runner/work/Gravitas/Gravitas/src/Gravitas/Support/LifecycleHooks/LifecycleHookHandler.cs
Line coverage
100%
Covered lines: 30
Uncovered lines: 0
Coverable lines: 30
Total lines: 99
Line coverage: 100%
Branch coverage
100%
Covered branches: 10
Total branches: 10
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
RegisterHook(...)100%66100%
UnregisterHook(...)100%11100%
InvokeHooks(...)100%22100%
CompareHook()100%22100%

File(s)

/home/runner/work/Gravitas/Gravitas/src/Gravitas/Support/LifecycleHooks/LifecycleHookHandler.cs

#LineLine coverage
 1//=======================================================================
 2// LifecycleHookHandler.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2026–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using SwiftCollections;
 9using System;
 10using System.Collections.Generic;
 11
 12namespace Gravitas.Support;
 13
 14/// <summary>
 15/// Provides functionality to register, unregister, and invoke lifecycle hooks in a thread-safe manner.
 16/// </summary>
 17public class LifecycleHookHandler
 18{
 508319    private readonly object _lifecycleHookLock = new();
 20
 21    /// <summary>
 22    /// Registers a lifecycle hook with the specified owner, order, and callback.
 23    /// Hooks are executed in order of their specified order, and if orders are equal, they are sorted by owner name.
 24    /// The returned IDisposable can be used to unregister the hook when it is no longer needed.
 25    /// </summary>
 26    /// <param name="hooks">The list of hooks to register the new hook with.</param>
 27    /// <param name="owner">The owner of the hook, used to identify and manage the hook.</param>
 28    /// <param name="order">The order in which the hook should be executed relative to other hooks.</param>
 29    /// <param name="callback">The callback to invoke when the hook is executed.</param>
 30    /// <returns>An IDisposable that can be used to unregister the hook.</returns>
 31    /// <exception cref="ArgumentException">Thrown if the owner is null or whitespace.</exception>
 32    /// <exception cref="InvalidOperationException">Thrown if a hook with the same owner is already registered.</excepti
 33    public IDisposable RegisterHook(
 34        SwiftList<OrderedLifecycleHook> hooks,
 35        string owner,
 36        int order,
 37        Action callback)
 38    {
 1839        if (string.IsNullOrWhiteSpace(owner))
 140            throw new ArgumentException("Lifecycle hook owner cannot be null or whitespace.", nameof(owner));
 41
 1742        SwiftThrowHelper.ThrowIfNull(callback, nameof(callback));
 43
 1644        lock (_lifecycleHookLock)
 45        {
 3846            for (int i = 0; i < hooks.Count; i++)
 47            {
 448                if (hooks[i].Owner == owner)
 149                    throw new InvalidOperationException($"Lifecycle hook '{owner}' is already registered.");
 50            }
 51
 1552            hooks.Add(new OrderedLifecycleHook(owner, order, callback));
 1553            hooks.SortInPlace(CompareHook());
 1554        }
 55
 1556        return new LifecycleHookRegistration(() => UnregisterHook(hooks, owner));
 57    }
 58
 59    /// <summary>
 60    /// Unregisters a lifecycle hook based on the specified owner.
 61    /// </summary>
 62    /// <param name="hooks">The list of hooks to unregister the hook from.</param>
 63    /// <param name="owner">The owner of the hook to unregister.</param>
 64    public void UnregisterHook(SwiftList<OrderedLifecycleHook> hooks, string owner)
 65    {
 1566        lock (_lifecycleHookLock)
 67        {
 1568            hooks.RemoveAll(hook => hook.Owner == owner);
 1569        }
 1570    }
 71
 72    /// <summary>
 73    /// Invokes all registered lifecycle hooks in the order they were registered.
 74    /// </summary>
 75    /// <param name="hooks">The list of hooks to invoke.</param>
 76    public void InvokeHooks(SwiftList<OrderedLifecycleHook> hooks)
 77    {
 78        OrderedLifecycleHook[] snapshot;
 1279        lock (_lifecycleHookLock)
 80        {
 1281            snapshot = hooks.ToArray();
 1282        }
 83
 5084        for (int i = 0; i < snapshot.Length; i++)
 1685            snapshot[i].Callback();
 986    }
 87
 88    private static Comparer<OrderedLifecycleHook> CompareHook()
 89    {
 1590        return Comparer<OrderedLifecycleHook>.Create((left, right) =>
 1591        {
 1592            int orderCompare = left.Order.CompareTo(right.Order);
 1593            if (orderCompare != 0)
 1594                return orderCompare;
 1595
 1596            return StringComparer.Ordinal.Compare(left.Owner, right.Owner);
 1597        });
 98    }
 99}