This commit is contained in:
2025-10-27 17:39:18 -04:00
commit 31f723bea4
1579 changed files with 642409 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
namespace Prefab.Handler;
/// <summary>
/// Provides access to the current handler context for the executing operation.
/// </summary>
/// <remarks>Implementations of this interface allow components to retrieve or temporarily override the current
/// HandlerContext within a given scope. This is typically used to flow contextual information, such as user or request
/// data, through asynchronous or nested operations.</remarks>
public interface IHandlerContextAccessor
{
/// <summary>
/// Gets the current handler context for the ongoing operation, if one is available.
/// </summary>
HandlerContext? Current { get; }
/// <summary>
/// Sets the specified handler context as the current context for the duration of the returned disposable object's
/// lifetime.
/// </summary>
/// <remarks>Use the returned IDisposable in a using statement to ensure the previous context is restored
/// even if an exception occurs.</remarks>
/// <param name="handlerContext">The handler context to set as current. Cannot be null.</param>
/// <returns>An IDisposable that, when disposed, restores the previous handler context.</returns>
IDisposable Set(HandlerContext handlerContext);
}
/// <inheritdoc cref="IHandlerContextAccessor"/>
public sealed class HandlerContextAccessor : IHandlerContextAccessor
{
private static readonly AsyncLocal<HandlerContext?> CurrentContext = new();
/// <inheritdoc cref="IHandlerContextAccessor"/>
public HandlerContext? Current => CurrentContext.Value;
/// <inheritdoc cref="IHandlerContextAccessor"/>
public IDisposable Set(HandlerContext handlerContext)
{
var previous = CurrentContext.Value;
CurrentContext.Value = handlerContext;
return new Scope(() => CurrentContext.Value = previous);
}
/// <summary>
/// Provides a mechanism for executing a specified delegate when the scope is disposed, typically used to restore
/// state or perform cleanup actions.
/// </summary>
/// <remarks>This type is intended for use with the 'using' statement to ensure that the specified
/// delegate is executed exactly once when the scope ends. The delegate is not invoked if Dispose is called more
/// than once.</remarks>
/// <param name="restore">The delegate to invoke when the scope is disposed. Cannot be null.</param>
private sealed class Scope(Action restore) : IDisposable
{
private bool _done;
public void Dispose()
{
if(_done)
return;
_done = true;
restore();
}
}
}