3

I have a custom convention that requires localized strings inside of it. AFAIK the only way to instantiate an IStringLocalizer is DependencyInjection.

How can I use an IStringLocalizer inside of my CustomConvention?

The convention isregistered like this

public void ConfigureServices(IServiceCollection services)
{
     //First I register the localization settings
     services.AddLocalization(o =>
     {
        o.ResourcesPath = "Resources";
     });

      services.AddMvc(options =>
      {
           //My custom convention, I would need to inject an IStringLocalizer  
           //into constructor here, but I can' instantiate it
           options.Conventions.Add(new LocalizationRouteConvention());
      })
}
Anarion
  • 2,406
  • 3
  • 28
  • 42

2 Answers2

4

The solution I had is not pretty.

You can do something like that, build the service provider to get an instance of the StringLocalizer.

public void ConfigureServices(IServiceCollection services)
{
     //First I register the localization settings
     services.AddLocalization(o =>
     {
        o.ResourcesPath = "Resources";
     });

     var stringLocalizer = services.BuildServiceProvider().GetService<IStringLocalizer<Resource>>();

     services.AddMvc(options =>
     {
          //My custom convention, I would need to inject an IStringLocalizer  
          //into constructor here, but I can' instantiate it
          options.Conventions.Add(new LocalizationRouteConvention(stringLocalizer));
     })
}
hockeylagu
  • 86
  • 4
0

I would suggest the approach provided here https://stackoverflow.com/a/61958762/4627333.

You basically just need to register your types and create an implementation of IConfigureOptions<MvcOptions> expecting your convention implementation. The DI will do the rest.

public class LocalizationRouteConventionMvcOptions : IConfigureOptions<MvcOptions>
{
    private readonly LocalizationRouteConvention _convention;

    public MyMvcOptions(LocalizationRouteConvention convention)
        => _convention = convention;

    public void Configure(MvcOptions options)
        => options.Conventions.Add(_convention);
}

public void ConfigureServices(IServiceCollection services)
{
    // or scoped, or transient, as necessary for your service
    services.AddTransient<IStringLocalizer<Resource>, MyStringLocalizer>();
    services.AddSingleton<LocalizationRouteConvention>();
    services.AddSingleton<IConfigureOptions<MvcOptions>, LocalizationRouteConventionMvcOptions>();

    services.AddControllers();
}

Your LocalizationRouteConvention code:

public sealed class LocalizationRouteConvention : IApplicationModelConvention
{
    private readonly IStringLocalizer<Resource> _stringLocalizer;

    public LocalizationRouteConvention(IStringLocalizer<Resource> stringLocalizer)
    {
        _stringLocalizer = stringLocalizer ?? throw new ArgumentNullException(nameof(stringLocalizer));
    }

    public void Apply(ApplicationModel application)
    {
        // ...
    }
}
Alexz S.
  • 2,366
  • 4
  • 21
  • 34