代码之家  ›  专栏  ›  技术社区  ›  lbrahim

如何将依赖项从自定义中间件传递到控制器中?

  •  1
  • lbrahim  · 技术社区  · 6 年前

    我有一个自定义中间件,我想从中添加一个范围依赖项。

    public class MyMiddleware {
        private readonly RequestDelegate _next;
    
        public MyMiddleware(RequestDelegate next)
        {
            _next = next;
        }
    
        public async Task Invoke(HttpContext httpContext,
            IOptionsSnapshot<ApiClientHttpSettings> settings,
            IServiceCollection services)
        {
            services.AddScoped<ICustomer>(new Customer());
    
            await _next(httpContext);
        }
    }
    

    所以我可以把它放到控制器里:

    public class CustomerController : ControllerBase
    {
        public ControllerBase(ICustomer customer)
        {
    
        }    
    }
    

    但在中间件中 IServiceCollection 无法解决。 我想这样做是因为有很多逻辑可以解决涉及的DI。

    我也可以试着在里面做 ConfigureServices 但那我就无法接触到 IOptionsSnapshot<SupplyApiClientHttpSettings> settings 我需要每一个请求。

    任何指向正确方向的指针都非常感谢。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Shaun Luttin    6 年前

    我也可以试着在里面做 ConfigureServices 但是我不能进入 IOptionsSnapshot<SupplyApiClientHttpSettings> 我需要为每个请求设置。

    以下是您如何访问 IOptionsSnapshot 在自定义服务中。完整来源是 here in GitHub .

    创建设置类。

    public class SupplyApiClientHttpSettings
    {
        public string SomeValue { get; set; }
    }
    

    在配置中为其添加一个值(例如 appsettings.json )

    {
        "someValue": "Value from appsettings"
    }
    

    定义服务并注入 操作快照 投入其中。

    public class CustomerService
    {
        private readonly SupplyApiClientHttpSettings settings;
    
        public CustomerService(IOptionsSnapshot<SupplyApiClientHttpSettings> options)
        {
            this.settings = options.Value;
        }
    
        public Customer GetCustomer()
        {
            return new Customer
            {
                SomeValue = settings.SomeValue
            };
        }
    }
    

    将您的配置、选项和服务连接在一起 Startup .

    public class Startup
    {
        IConfiguration Configuration;
    
        public Startup()
        {
            Configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .Build();
        }
    
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<SupplyApiClientHttpSettings>(Configuration);
            services.AddScoped<CustomerService>();
            services.AddMvc();
        }
    
        public void Configure(IApplicationBuilder app)
        {
            app.UseMvcWithDefaultRoute();
        }
    }
    

    将服务注入控制器。使用该服务为客户提供最新的选项快照。

    public class CustomerController : Controller
    {
        private readonly CustomerService customerService;
    
        public CustomerController(CustomerService customerService)
        {
            this.customerService = customerService;
        }
    
        public IActionResult Index() 
        {
            return Json(customerService.GetCustomer());
        }
    }
    

    这是完整的资料来源 in GitHub .

        2
  •  0
  •   lbrahim    6 年前

    答案很简单,很接近。以下就是我必须做的:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<ICustomer>(provider => {
            var settings = Configuration.GetSection("ApiClientHttpSettings").Get<ApiClientHttpSettings>();
            return new Customer(settings.Name, settings.Age);
        });
    }
    

    上面为我勾选了所有框:

    1. 每个请求的新实例
    2. 能够在请求时读取更新的配置
    3. 根据自定义逻辑创建实例