为了账号安全,请及时绑定邮箱和手机立即绑定

中间件向 DI 容器或服务添加新的依赖项

中间件向 DI 容器或服务添加新的依赖项

C#
守候你守候我 2023-08-20 09:47:34
我正在编写一个中间件(也许我想要一个范围服务??),我想我的计划是拥有某种多租户场景。例如,如果我有 2 个响应此服务的域:www.domain1.comwww.domain2.com我想在请求启动时捕获请求,查看正在使用的主机名,然后通过依赖注入将其他一些对象设置为可用于管道中的所有内容。看来中间件应该是实现这一目标的正确方法,但不确定如何执行最后一步。我的选择似乎是:中间件注册Singleton服务来访问数据库尽早注册成为第一个捕获请求的中间件。分析请求对象并构建自定义配置对象将自定义配置作为范围对象添加到 DI 容器以供其他服务使用服务注册Singleton服务来访问数据库为 IHttpContextAccessor 注册 Singleton 服务注册范围?服务——相当于中间件分析请求对象并构建自定义配置对象将自定义对象注册为 DI 容器中的新作用域对象我的假设是服务能够注册自定义范围的对象,因为它仍在ConfigureServicesstartup.cs的方法中然而,对于中间件来说,它是通过ConfigureDI 容器已经构建完成的方法来初始化的?
查看完整描述

1 回答

?
ITMISS

TA贡献1871条经验 获得超8个赞

您可以使用工厂重载来AddScoped实现您希望每个租户/请求都不同的服务。这是一个例子:

services.AddScoped<IServiceForTenant>(sp =>

{

    var httpContextAccessor = sp.GetRequiredService<IHttpContextAccessor>();

    var serviceForTenant = new ServiceForTenant();


    // TODO: Use httpContextAcccessor.HttpContext to configure serviceForTenant.


    return serviceForTenant;

});

对于进入 ASP.NET Core 应用程序的每个请求,上面的代码将在您首次IServiceForTenant在控制器中发出请求时运行。此时,您的代码可以读取IHttpContextAccessor.HttpContext并做出所需的任何决策,以便为IServiceForTenant. 然后,该相同的实例将用于请求的其余部分(即管道的更上游)。


传入的参数AddScoped是Func<IServiceProvider, T>. 您需要在这里提供某种委托,这可以通过多种方式之一来完成。以下是一些示例:


您可以将调用包装到其自己的扩展方法中,如下所示:


public static void AddServiceForTenant(this IServiceCollection services)

{

    services.AddScoped<IServiceForTenant>(sp =>

    {

        // ...

    });

}

在ConfigureServices:


services.AddServiceForTenant();

使用带有方法的类static:


public static class ServiceForTenantFactory

{

    public static ITenantForService Create(IServiceProvider sp)

    {

        // ...

    }

}

在ConfigureServices:


services.AddScoped(ServiceForTenantFactory.Create);

使用带有实例方法的类:


public class ServiceForTenantFactory

{

    public ITenantForService Create(HttpContext httpContext)

    {

        // ...

    }

}

在ConfigureServices:


services.AddScoped(sp =>

{

    var httpContextAccessor = sp.GetRequiredService<IHttpContextAccessor>();

    var serviceForTenantFactory = new ServiceForTenantFactory(); // Or use DI.


    return serviceForTenantFactory.Create(httpContextAccessor.HttpContext);

});

最后一个选项是最灵活的,因为您甚至可以ServiceForTenantFactory从 DI 解析自身,并且它可以有自己的依赖项等。另请注意,Create这里直接采用HttpContext(作为示例)。


正如我已经说过的,还有比所示的三个更多的选项,但这应该是一个很好的使用基础。


查看完整回答
反对 回复 2023-08-20
  • 1 回答
  • 0 关注
  • 67 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信