首页 文章

在ASP.NET核心中注入中间件服务

提问于
浏览
5

我想基于HTTP标头值注入服务 . 所以我有两个类--DbDataProvider和InMemDataProvider,都是从IDataProvider实现的 . 每当进行API调用时,客户端都会传递一个标头,该标头确定是否需要DbDataProvider或者是否需要InMemDataProvider . 我如何实现这一目标?所以简而言之,我需要在其中一个中间件中的ServiceCollection中注入服务 . 那可能吗?

问题是在Startup类的ConfigureService方法中我无法获取HttpContext . 我编写了一个中间件,使用它可以获取HTTP上下文但是如何在那里注入服务?

2 回答

  • 2

    没有简单或干净的方法来做到这一点 . 您无法修改 ConfigureServices 方法之外的 IServiceCollection . 但即使你可以,也没用,因为在调用 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();
        }
    }
    
  • 6

    Tsen的上述答案是正确的 . 你应该实施一个工厂 .

    但此外,您还可以将工厂方法注册到服务集合 . 像这样:

    Services.AddTransient(serviceProvider => serviceProvider.GetService<IDataProviderFactory>().Create())
    

    这会注册您的IDataProvider . 在Create中,您应该评估该HTTP标头值,以便它返回正确的IDataProvider实例 . 然后在您需要它的任何类中,您只需通过构造函数请求IDataProvider,并且容器将提供正确的实现 .

相关问题