I'm trying to setup localization following this documentation
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/localization
I assume that if you use the built in DI it just works however I'm using Simple Injector instead of the build in DI in so it complains that I haven't registered the IStringLocalizer. How do I go about registering IStringLocalizer as I obviously can't do this
container.Register<IStringLocalizer, StringLocalizer>(Lifestyle.Scoped);
Thanks
To get localization working in ASP.NET Core, you will have to call AddLocalization()
from within your ConfigureServices
method and enable auto cross-wiring:
public void ConfigureServices(IServiceCollection services) {
services.AddLocalization(); // ** Add localization to ASP.NET Core **
// Normal MVC stuff
services.AddMvc();
// Simple Injector integration
IntegrationSimpleInjector(services);
}
private void IntegrationSimpleInjector(IServiceCollection services) {
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IControllerActivator>(
new SimpleInjectorControllerActivator(container));
services.EnableSimpleInjectorCrossWiring(container);
services.UseSimpleInjectorAspNetRequestScoping(container);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
// This call allows Simple Injector to resolve anything from ASP.NET Core.
container.AutoCrossWireAspNetComponents(app); // ** Enable auto cross-wiring ***
// NOTE: If you're still running .NET Core v1.x, auto cross-wiring will not be
// available. In that case, you can make the following call to CrossWire<T>
// to register StringLocalizer<T>'s dependency explicitly.
// container.CrossWire<IStringLocalizerFactory>(app);
// Your usual startup stuff here
}
The call to services.AddLocalization()
adds to appropriate registrations to the ASP.NET Core configuration system, but that by itself doesn't allow Simple Injector to get to it. Simple Injector v4.1 however contains an AutoCrossWireAspNetComponents
extension method that allows the container to go look for missing dependencies in the ASP.NET Core configuration system.
This is all you need to get things up and running, but we can do better...
Because of limitations in the built-in ASP.NET Core DI container, you are forced to inject generic abstractions such as ILogger<T>
and IStringLocalizer<T>
where T
will always be the consuming type itself. What this means is that when such dependency required in HomeController
, you need to inject an ILogger<HomeController>
and IStringLocalizer<HomeController>
. It would be much cleaner, more maintainable, and safer to be able to inject the non-generic ILogger
and IStringLocalizer
abstractions, and let the DI container automatically find the correct generic implementation to implement.
Unfortunately, the built-in DI container does not support this. But most mature DI libraries actually do support this, as does Simple Injector.
The following registration, allows any application component to depend on the non-generic IStringLocalizer
and Simple Injector will inject a generic StringLocalizer<T>
where T
becomes the consuming type, thus still getting a localizer for that particular class.
container.RegisterConditional(
typeof(IStringLocalizer),
c => typeof(StringLocalizer<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
With this registration, your HomeController
can no depend on IStringLocalizer
as shown below:
public class HomeController : Controller
{
private readonly IStringLocalizer localizer;
public HomeController(IStringLocalizer localizer)
{
this.localizer = localizer;
}
}