在运行时将请求范围的对象注入 asp.net 核心



我在 ASP.NET Core管道中有一个中间件,我在运行时注入了一个对象,如下所示

public async Task Invoke(HttpContext context)
{
 _container.Inject(someObject);
 await _requestDelegate(context);
}

我现在面临的问题是,对于每个请求,它都会注入一个实例,并且使我的容器膨胀。如果我做_container.GetAllInstances<SomeType>(),我会得到 100+ 个对象。有没有办法可以注入范围为请求的对象并在请求完成后释放对象?

不应在运行时为每个请求配置依赖关系注入,而应在应用程序启动时为整个应用程序配置依赖项注入。

对于每个请求实例,使用 HttpContext.Items 管理请求数据是一种更好的方法。它是一个键值存储,用于单个 HTTP 请求中的共享对象。

在中间件中,您可以将对象添加到HttpContext.Items集合中: context.Items.Add("someObjectKey", someObject);

然后在控制器(或任何拥有 HttpContext 的地方(中,您可以获取对象:

if (context.Items.TryGetValue("someObjectKey", out object objSomeObject) 
    && objSomeObject is SomeObjectType someObject)) {
    // Do anything with your object here
}

如果确实要使用 DI,可以创建一个具有作用域生存期的帮助程序类,该类获取具有 IHttpContextAccessor 的当前HttpContext,并以类型安全的方式提供对象。

public class SomeObjectAccessor
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public SomeObjectAccessor(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }
    public SomeObject Object {
        get
        {
            if (_httpContextAccessor.HttpContext?.Items != null && _httpContextAccessor.HttpContext.Items.TryGetValue("someObjectKey", out object objSomeObject))
                return objSomeObject as SomeObject;
            return null;
        }
    }
}

或者,该类也可以充当工厂,并在首次访问时基于 HttpContext 创建对象,然后您将不使用 HttpContext.Items 。 但这取决于这里的用例。

目前还不清楚你想做什么。在运行时为每个请求注入对象的目的是什么?

使用 ServicesCollection 在 ConfigureServices 方法中设置 DI,并使用内置的 AddScoped 方法注入对特定请求有效的对象。

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped(typeof(someclass), someObject);
}

如果您需要访问中间件中某个对象的实例。只需将依赖项作为附加参数添加到 Invoke 方法即可

public async Task Invoke(HttpContext context, IYourDependency someObject)
{
    await _requestDelegate(context);
}

我希望这有帮助