66 lines
2.6 KiB
C#
66 lines
2.6 KiB
C#
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();
|
|
}
|
|
}
|
|
} |