IStringLocalizer与第三方DI

时间:2017-07-21 09:04:41

标签: simple-injector asp.net-core-localization

我尝试按照此文档设置本地化

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

我认为如果你使用内置DI它只是工作,但是我使用Simple Injector而不是在DI中构建,所以它抱怨我没有注册IStringLocalizer。我如何注册IStringLocalizer,因为我显然无法做到这一点

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

由于

2 个答案:

答案 0 :(得分:3)

要在ASP.NET Core中使用本地化,您必须在AddLocalization()方法中调用ConfigureServices并启用自动交叉连接

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
}

services.AddLocalization()的调用增加了对ASP.NET Core配置系统的适当注册,但是它本身不允许Simple Injector到达它。然而,Simple Injector v4.1包含一个AutoCrossWireAspNetComponents扩展方法,允许容器在ASP.NET Core配置系统中查找缺少的依赖项。

这就是你需要做的事情,但我们可以做得更好......

由于内置ASP.NET Core DI容器的限制,您必须注入ILogger<T>IStringLocalizer<T>这样的通用抽象,其中T始终< / em>是消费类型本身。这意味着当HomeController中需要这种依赖时,您需要注入ILogger<HomeController>IStringLocalizer<HomeController>。能够注入非通用ILoggerIStringLocalizer抽象,并且让DI容器自动找到要实现的正确通用实现,它会更清晰,更易于维护和更安全。

不幸的是,内置的DI容器支持这个。但是,大多数成熟的DI库实际上支持这一点,就像Simple Injector一样。

以下注册允许任何应用程序组件依赖于非泛型IStringLocalizer,而Simple Injector将注入通用StringLocalizer<T>,其中T成为消费类型,因此仍然获得特定类的本地化程序。

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

通过此注册,您的HomeController无法依赖IStringLocalizer,如下所示:

public class HomeController : Controller
{
    private readonly IStringLocalizer localizer;

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

答案 1 :(得分:1)

我知道这已经过时了,但是我发现这篇文章的目的是做同样的事情,但我根据我使用的ILogger注册采取了不同的方法。所以这就是我在控制器和服务中获得强类型IStringLocalizers的方法。

交叉连接StringLocalizerFactory

container.CrossWire<IStringLocalizerFactory>(app);

然后使用RegisterConditional

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

然后我可以将非通用IStringLocalizer注入我的控制器等,它将是正确的类型。例如,如果我使用以下构造函数

public MyController(IStringLocalizer localiser)...

然后localiser将是

类型
IStringLocalizer<MyController>

这是ASP.NET Core MVC 2&amp;简单的注射器4.1。我想知道steven是否对此方法有任何评论?