在 mvc 中使用依赖注入

Working with dependency injection in mvc

在我们的一个应用程序中,我已经在使用 AppTenant class 的依赖注入,如下所示

public void ConfigureServices(IServiceCollection services)
{

services.AddMultitenancy<AppTenant, CachingAppTenantResolver>();
services.Configure<MultitenancyOptions>(Configuration.GetSection("Multitenancy"));
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
 app.UseMultitenancy<AppTenant>();
}

在控制器中,我可以按如下方式轻松访问它

public AccountController(AppTenant tenant)
    {
        this.tenant = tenant;
    }

现在,我想在同一解决方案中访问其他项目 class 中的相同 AppTenantHttpContext。 所以,我试过这样

public SqlStringLocalizerFactory(
       AppTenant tenant)
    {
     _tenant = tenant;

    }

但它即将变为空,所以我需要做的是在另一个项目中获得 AppTenantHttpContext class ?

对于SqlStringLocalizerFactoryclass,服务是用[=​​20=]方法编写的,如下

public static class SqlLocalizationServiceCollectionExtensions
{

    public static IServiceCollection AddSqlLocalization(this IServiceCollection services)
    {
        if (services == null)
        {
            throw new ArgumentNullException(nameof(services));
        }

        return AddSqlLocalization(services, setupAction: null);
    }

   public static IServiceCollection AddSqlLocalization(
        this IServiceCollection services,
       Action<SqlLocalizationOptions> setupAction)
    {

            if (services == null)
        {
            throw new ArgumentNullException(nameof(services));
        }

        services.TryAdd(new ServiceDescriptor(
            typeof(IStringExtendedLocalizerFactory),
            typeof(SqlStringLocalizerFactory),
            ServiceLifetime.Singleton));
        services.TryAdd(new ServiceDescriptor(
            typeof(IStringLocalizerFactory),
            typeof(SqlStringLocalizerFactory),
            ServiceLifetime.Singleton));
        services.TryAdd(new ServiceDescriptor(
            typeof(IStringLocalizer),
            typeof(SqlStringLocalizer),
            ServiceLifetime.Singleton));

        if (setupAction != null)
        {
            services.Configure(setupAction);
        }
        return services;
    }
}

我什至尝试过 IHttpContextAccessor,但仍然没有成功。

感谢任何帮助!

编辑-2

新解决方案:

public SqlStringLocalizerFactory(IHttpContextAccessor _accessor)
{
   _accessor= accessor;
}
public void SomeMethod()
{
    var tenant = _accessor.HttpContext.RequestServices
            .GetRequiredService<AppTenant>();
}

Edit : IServiceProvider 方式不符合我的预期。参见@Sock 的解决方案

首先,我假设问题的发生是由于@qujck 指出的俘虏依赖。为了避免俘虏依赖:

如果SqlStringLocalizerFactory的生命周期必须是单例(某些情况下必须是),在这个 案例使用 IServiceProvider:

public SqlStringLocalizerFactory(IServiceProvider serviceProvider)
{
   _serviceProvider = serviceProvider;
}
public void SomeMethod()
{
    var tenant =  _serviceProvider.GetService<AppTenant>();
}

否则使用 AddScoped 对你的情况来说似乎是合理的。

你有两个选择,最好的选择,如果 SqlStringLocalizerFactory 可以是范围内的依赖项(你为每个请求获得一个新实例)那么你可以将它注册为范围内的依赖项:

services.TryAdd(new ServiceDescriptor(
        typeof(IStringLocalizerFactory),
        typeof(SqlStringLocalizerFactory),
        ServiceLifetime.Scoped));

如果 SqlStringLocalizerFactory 必须 是单例依赖项,那么您需要确保使用 ServiceSope 解决租户的作用域依赖项:

public class SqlStringLocalizerFactory
{
    private readonly IServiceProvider _serviceProvider;

    public SqlStringLocalizerFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public void SomeMethod()
    {
        using (var serviceScope = _serviceProvider
            .GetRequiredService<IServiceScopeFactory>().CreateScope())
        {
            var tenant = serviceScope.ServiceProvider.GetService<AppTenant>();

            // do something with tenant...
        }
    }
}