环境数据作为AsyncLocal

问题描述

我创建了一个AmbientDataProvider,旨在访问许多请求中设置的查询参数。在某些情况下,我想手动进行设置,例如

[HttpGet]
public IHttpActionResult SomeAction()
{
    _ambientDataProvider.SetRequestId("123");

    return Ok();
} 

是否有必要将其保留为下面的AsyncLocal?由于班级的生活方式有限,我想我也可以使用私有字符串吗?

public class AmbientDataProvider : IAmbientDataProvider
{
    private readonly AsyncLocal<string> _requestId = new AsyncLocal<string>();
    public string RequestId => _requestId.Value ?? HttpContext.Current?.Request.QueryString["requestId"];

    public void SetRequestId(string requestId)
    {
        _requestId.Value = requestId;
    }
}

我的容器配置

container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
container.Register<IAmbientDataProvider,AmbientDataProvider>(Lifestyle.Scoped);

解决方法

在通过对象图推送运行时数据时,有两个DI Composition Models可供选择:Ambient Composition ModelClosure Composition Model

您似乎混合了两种模型。使用Closure Composition Model,可以将运行时数据(您的请求ID)存储在组件内部的(私有)字段中,而使用Ambient Composition Model,则可以将运行时数据存储为环境状态(例如,使用AsyncLocal<T>)。 / p>

使用环境组合模型时,可以使AmbientDataProvider单身,因为AsyncLocal<T>已经确保每个请求的运行时数据隔离。但是,当您的数据提供者是“合并范围”组件时,您也可以将数据存储在私有字段中。