IStringLocalizer with third party DI

I am trying to set up localization following this documentation

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization

I guess if you are using inline DI it just works, but I am using Simple Injector instead of assembling in DI, so it complains that I haven't registered the IStringLocalizer. How do I go about registering the IStringLocalizer as I obviously cannot do this

container.Register<IStringLocalizer, StringLocalizer>(Lifestyle.Scoped);

      

thank

+3


source to share


2 answers


To get localization in ASP.NET Core you will have to call AddLocalization()

from your method ConfigureServices

and enable automatic cross-layout:

public void ConfigureServices(IServiceCollection services)
{
    // ** Add localization to ASP.NET Core **
    services.AddLocalization();

    // 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)
{
    // ** Enable auto cross-wiring ***
    // This call allows Simple Injector to resolve anything from ASP.NET Core.
    container.AutoCrossWireAspNetComponents(app);

    // Your usual startup stuff here
}

      

The call services.AddLocalization()

adds the appropriate registrations to the ASP.NET Core config system, but by itself prevents Simple Injector from reaching it. However, Simple Injector v4.1 contains an extension method AutoCrossWireAspNetComponents

that allows the container to look for missing dependencies in the ASP.NET core configuration system.

That's all you need to get things working out, but we can do better ...

Due to limitations in the built-in Core Core.NET container, you are forced to introduce generic abstractions such as ILogger<T>

and IStringLocalizer<T>

where T

will always be the most consuming type. This means that when such a dependency is required in HomeController

, you need to enter ILogger<HomeController>

and IStringLocalizer<HomeController>

. It would be much cleaner, more maintainable, and more secure to be able to introduce abstractions without generating ILogger

and IStringLocalizer

, 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 do support this, as does Simple Injector.

The following registration allows any application component to depend on non-generic IStringLocalizer

and Simple Injector will inject a generic StringLocalizer<T>

where T

it becomes a 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 yours HomeController

cannot depend on IStringLocalizer

as shown below:

public class HomeController : Controller
{
    private readonly IStringLocalizer localizer;

    public HomeController(IStringLocalizer localizer)
    {
        this.localizer = localizer;
    }
}

      

+3


source


I know this is old, but I came across this post looking to do the same, but I took a different approach based on the ILogger registration I was using. So here is what I do to get strongly typed IStringLocalizers in my controllers and services.

Traverse StringLocalizerFactory

container.CrossWire<IStringLocalizerFactory>(app);

      

Then use RegisterConditional

 container.RegisterConditional(
                    typeof(IStringLocalizer),
                    c => typeof(StringLocalizer<>).MakeGenericType(c.Consumer.ImplementationType),
                    Lifestyle.Singleton,
                    c => true);

      



And then I can insert a non-original IStringLocalizer into my controllers etc. and it will be of the correct type. For example, if I use the following constructor

public MyController(IStringLocalizer localiser)...

      

Then the localizer will have the type

IStringLocalizer<MyController>

      

This is with ASP.NET Core MVC 2 and Simple Injector 4.1. I wonder if steven has a comment on this approach?

0


source







All Articles