Reputation: 3657
In one of our app I am already using the dependency injection of AppTenant
class like follows
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>();
}
and in controller i am able to access it easily as follows
public AccountController(AppTenant tenant)
{
this.tenant = tenant;
}
Now, I want to access the same AppTenant
OR HttpContext
in other project class in the same solution.
So, I have tried like this
public SqlStringLocalizerFactory(
AppTenant tenant)
{
_tenant = tenant;
}
But it is coming null, so what I need to do, to get the AppTenant
OR HttpContext
in the other project class ?
For SqlStringLocalizerFactory
class the services are written in ConfigureServices
method like follows
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;
}
}
I have even tried with IHttpContextAccessor
, but still not getting any success.
Any help on this appreciated !
Upvotes: 1
Views: 578
Reputation: 24123
Edit-2
New Solution:
public SqlStringLocalizerFactory(IHttpContextAccessor _accessor)
{
_accessor= accessor;
}
public void SomeMethod()
{
var tenant = _accessor.HttpContext.RequestServices
.GetRequiredService<AppTenant>();
}
Edit : IServiceProvider
way doesn't work as i expect. See @Sock's solution
First, i assumes the problem occurs because of captive dependency as pointed by @qujck. To avoid captive dependency:
If lifetime of SqlStringLocalizerFactory
must be singleton(some cases must be), in this
case use IServiceProvider
:
public SqlStringLocalizerFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public void SomeMethod()
{
var tenant = _serviceProvider.GetService<AppTenant>();
}
Otherwise using AddScoped
seems reasonable for your case.
Upvotes: 2
Reputation: 5413
You have two options, the best option, if the SqlStringLocalizerFactory
can be a scoped dependency (you get a new instance for every request) then you can register it as a scoped dependency:
services.TryAdd(new ServiceDescriptor(
typeof(IStringLocalizerFactory),
typeof(SqlStringLocalizerFactory),
ServiceLifetime.Scoped));
If the SqlStringLocalizerFactory
must be a a Singleton dependency, then you need to make sure you resolve a scoped dependency for the Tenant by using a 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...
}
}
}
Upvotes: 2