onebeyond/onebeyond-studio-core

View on GitHub
src/OneBeyond.Studio.Crosscuts/Utilities/LogicalCallContext/LogicalCallContext.cs

Summary

Maintainability
A
0 mins
Test Coverage
using System.Collections.Concurrent;
using System.Threading;

namespace OneBeyond.Studio.Crosscuts.Utilities.LogicalCallContext;

/// <summary>
/// Provides a way to set contextual data that flows with the call and 
/// async context of a test or invocation.
/// </summary>
public static class LogicalCallContext
{
    private static readonly ConcurrentDictionary<string, AsyncLocal<object?>> State =
        new ConcurrentDictionary<string, AsyncLocal<object?>>();

    /// <summary>
    /// Stores a given object and associates it with the specified name.
    /// </summary>
    /// <param name="name">The name with which to associate the new item in the call context.</param>
    /// <param name="data">The object to store in the call context.</param>
    public static void SetData(string name, object? data)
    {
        State.GetOrAdd(name, _ => new AsyncLocal<object?>()).Value = data;
    }

    /// <summary>
    /// Retrieves an object with the specified name from the <see cref="LogicalCallContext"/>.
    /// </summary>
    /// <param name="name">The name of the item in the call context.</param>
    /// <returns>The object in the call context associated with the specified name, or <see langword="null"/> if not found.</returns>
    public static T FindData<T>(string name)
    {
        var dataValue = State.TryGetValue(name, out var data)
            ? data.Value
            : null;
        return (T)dataValue!;
    }
}