.NET Core等效于CallContext.LogicalGet / SetData

时间:2017-02-15 06:35:03

标签: .net-core callcontext

我正在尝试将.net核心转移到使用CallContext.LogicalGet / SetData的现有.net应用程序。

当Web请求到达应用程序时,我在CallContext中保存了CorrelationId,每当我需要稍后在轨道上记录某些内容时,我可以轻松地从CallContext中收集它,而无需在任何地方传输它。

因为.net核心不再支持CallContext,因为它是System.Messaging的一部分。记录了哪些选项?

我看到的一个版本是AsyncLocal可以使用(How do the semantics of AsyncLocal differ from the logical call context?),但看起来好像我必须传输这个变量才能超越目的,这不方便。

3 个答案:

答案 0 :(得分:4)

当我们将库从.Net Framework切换到.Net Standard并不得不替换System.Runtime.Remoting.Messaging CallContext.LogicalGetDataCallContext.LogicalSetData时,出现了此问题。

我按照本指南替换了方法:

http://www.cazzulino.com/callcontext-netstandard-netcore.html

/// <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 CallContext
{
    static 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="CallContext"/>.
    /// </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 object GetData(string name) =>
        state.TryGetValue(name, out AsyncLocal<object> data) ? data.Value : null;
}

答案 1 :(得分:2)

您可以使用AsyncLocal词典来精确模拟原始CallContext的API和行为。有关完整的实现示例,请参见http://www.cazzulino.com/callcontext-netstandard-netcore.html

答案 2 :(得分:1)

我猜你可以使用ThreadStatic,因为我听到CallContext是/只是“只是”对ThreadStatic的抽象,在调用堆栈中的线程之间自动传输状态。

此外,您可以/应该使用AsyncLocal / ThreadLocal。 AsyncLocal几乎就像CallContext一样。