Pra*_*rya 8 dependency-injection asp.net-core asp.net-core-middleware
我想基于HTTP标头值注入服务.所以我有两个类--DbDataProvider和InMemDataProvider,都是从IDataProvider实现的.每当进行API调用时,客户端都会传递一个标头,该标头确定是否需要DbDataProvider或者是否需要InMemDataProvider.我如何实现这一目标?所以简而言之,我需要在其中一个中间件中的ServiceCollection中注入服务.那可能吗?
问题是在Startup类的ConfigureService方法中我无法获取HttpContext.我编写了一个中间件,使用它可以获取HTTP上下文但是如何在那里注入服务?
没有简单或干净的方法来做到这一点.您无法修改方法的IServiceCollection外部ConfigureServices.但即使你可以,也没用,因为容器在Configure被调用之前就已经被构建了.
你可以做的是创建一个工厂类并将其注册为作用域.
public interface IDataProviderFactory
{
    bool UseInMemoryProvider { get; set; }
    IDataProvider Create();
}
public class DataProviderFactory : IDataProviderFactory
{
    private readonly IServiceProvider provider;
    public bool UseInMemoryProvider { get; set; }
    public DataProviderFactory(IServiceProvider provider) 
    {
        this.provider = provider;
    }
    public IDataProvider Create()
    {
        if(UseInMemoryProvider) 
        {
            return provider.RequestService<InMemoryDataProvider>();
        }
        return provider.RequestService<DbDataProvider>();
    }
}
然后在你的中间件中:
public class MyMiddleware
{
    public void Invoke(HttpContext context) 
    {
        var dataProviderFactory = context.RequestServices.RequestService<IDataProviderFactory>();
        // Your logic here
        if(...)
        {
            dataProviderFactory.UseInMemoryStore = true;
        } 
    }
}
在您的控制器/服务中:
public class MyController : Controller 
{
    private readonly IDataProvider dataProvider;
    public MyController(IDataProviderFactory dataProviderFactory)
    {
        dataProvider = dataProviderFactory.Create();
    }
}
您可以在 中的 DI 配置中实现此目的Startup.cs。
它们的关键是services.AddHttpContextAccessor()允许您访问 HttpContext。
services.AddHttpContextAccessor();
services.AddScoped<DbDataProvider>();
services.AddScoped<InMemDataProvider>();
services.AddScoped<IDataProvider>(ctx =>
{
    var contextAccessor = ctx.GetService<IHttpContextAccessor>();
    var httpContext = contextAccessor.HttpContext;
    // Whatever the header is that you are looking for
    if (httpContext.Request.Headers.TryGetValue("Synthetic", out var syth))
    {
        return ctx.GetService<InMemDataProvider>();
    }
    else
    {
        return ctx.GetService<DbDataProvider>();
    }
});
| 归档时间: | 
 | 
| 查看次数: | 4924 次 | 
| 最近记录: |