4

I've got an ASP.NET Core application and I'd like to use different strategies based on the Route selected. As an example if someone navigates to /fr/Index I want to inject the French translation implementation into my Controller. Likewise when someone navigates to /de/Index I'd like the German translation injected.

This is to avoid having every single action on my Controller read the "language" parameter and pass it on.

From a higher level, I'd like to have something like that:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // Stuff here
    app.MapWhen(
        context => context.Request.Query["language"] == "fr", 
        builder =>
        {
            builder.Register<ILanguage>(FrenchLanguageImplementation);
        });

    app.MapWhen(
        context => context.Request.Query["language"] == "de",
        builder =>
        {
            builder.Register<ILanguage>(GermanLanguageImplementation);
        });
}

Unfortunately, it doesn't look like I get the IoC container resolving context at that level.

PS: I'm using Lamar as IoC.

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
R4cOOn
  • 2,340
  • 2
  • 30
  • 41

1 Answers1

3

You can use the AddScoped overload on IServiceCollection (or ServiceRegistry, which also implements IServiceCollection) to provide a factory-based service registration to the DI container. Here's an example implementation of ConfigureContainer, with explanatory comments inline:

public void ConfigureContainer(ServiceRegistry services)
{
    // ...

    // Register IHttpContextAccessor for use in the factory implementation below.
    services.AddHttpContextAccessor();

    // Create a scoped registration for ILanguage.
    // The implementation returned from the factory is tied to the incoming request.
    services.AddScoped<ILanguage>(sp =>
    {
        // Grab the current HttpContext via IHttpContextAccessor.
        var httpContext = sp.GetRequiredService<IHttpContextAccessor>().HttpContext;
        string requestLanguage = httpContext.Request.Query["language"];

        // Determine which implementation to use for the current request.
        return requestLanguage switch
        {
            "fr" => FrenchLanguageImplementation,
            "de" => GermanLanguageImplementation,
            _ => DefaultLanguageImplementation
        };
    });
}

Disclaimer: Up until testing the information in this answer, I've never used Lamar, so this Lamar-specific setup is taken from the docs and a best-guess effort. Without Lamar, the first line in the sample code would be public void ConfigureServices(IServiceCollection services) with no other changes.

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203