31

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

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

由于 CallContext 在.net 核心中不再受支持,因为它是 System.Messaging.Remoting 的一部分,有哪些选项?

我见过的一个版本是可以使用 AsyncLocal (AsyncLocal 的语义与逻辑调用上下文有何不同?),但看起来我必须将这个变量传输到所有地方,这超出了目的,它不是方便的。

4

2 回答 2

21

当我们将库从 .Net Framework 切换到 .Net Standard 并且不得不替换System.Runtime.Remoting.Messaging CallContext.LogicalGetData和.Net 时遇到了这个问题CallContext.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;
}
于 2018-11-08T16:17:44.163 回答
16

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

于 2018-09-15T21:14:08.440 回答