2017-05-27 200 views
0

我知道如何在派生自Controller的类中使用IStringLocalizer接口,例如如herehere所述。我可以在不是控制器的类中使用IStringLocalizer

在不从Controller派生的类中使用IStringLocalizer的正确方法是什么?

我找不到任何解决这个问题的例子。

是否总是需要将IStringLocalizer或IStringLocalizerFactory传递给构造函数?

注意。
我知道这是一个相当普遍的问题(而堆栈溢出是针对具体的编程问题)。背景是我为.NET项目制作了一个本地化工具。我正试图弄清楚我的工具必须对源代码进行哪些更改以支持ASP.NET Core项目中的本地化。

+0

'IStringLocalizer'通过ASP.NET Core内置的[DI容器](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection)解决。你可以在任何通过DI解析的类中的构造函数中注入'IStringLocalizer'。你可以试试吗? –

+0

谢谢@IlyaChumakov,我会试试看。我已经找到了另一个问题,并在上​​面解释了一下[https://stackoverflow.com/questions/37189984/dependency-injection-with-classes-other-than-a-controller-class]。事实上,我的问题接近于重复。 –

+0

是的,它看起来像这样。 –

回答

0

如果一个类派生自Controller,则无关紧要。

重要的是,您的对象是由依赖注入容器创建的,而不是使用新运算符创建的,如here所述。如果要在所有类中使用ASP.NET Core本地化机制,则必须采用此模式创建对象。

This page对如何创建对象给出了很好的说明,但我会尝试举例说明它如何与本地化配合使用。

我创建了一个MyHelper类。该类需要将本地化对象传递给构造函数。它包含一个属性Hello,它返回一个本地化的字符串。

namespace AddingLocalization.Classes 
{ 
    public class MyHelper 
    { 
    private readonly IStringLocalizer<MyHelper> _localizer; 

    public MyHelper(IStringLocalizer<MyHelper> localizer) 
    { 
     _localizer = localizer; 
    } 

    public string Hello 
    { 
     get 
     { 
     return _localizer["Hello World."]; 
     } 
    } 

    } 
} 

在启动类的方法ConfigureServices,我已经添加了样板代码描述here和添加了一行注册类MyHelper与依赖注入容器。

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddLocalization(opts => opts.ResourcesPath = "Resources"); 

    services.AddMvc() 
      .AddViewLocalization (
       LanguageViewLocationExpanderFormat.Suffix, 
       opts => opts.ResourcesPath = "Resources") 
      .AddDataAnnotationsLocalization(); 

    // This line registers the class MyHelper with the 
    // Dependency Injection Container.  
    services.AddTransient<MyHelper>(); 
} 

以我的控制器类,我加型MyHelper的参数给构造,其被存储在一个成员变量。

public class HomeController : Controller 
{ 
    private readonly IStringLocalizer<HomeController> _localizer ; 
    private readonly MyHelper       _h ; 

    public HomeController (IStringLocalizer<HomeController> localizer, 
          MyHelper       h) 
    { 
    _localizer = localizer; 
    _h   = h ; 
    } 

    ... 

    public IActionResult About() 
    { 
    ViewData["Message"] = _h.Hello ; 
    return View(); 
    } 

    ... 
} 

由于类MyHelper已经与依赖注入容器中注册时,它创建该对象并将其传递到自动构造。这是依赖注入容器执行的魔术。

在About()方法中,我从MyHelper对象获取属性。

这就是代码,但我想确定它会从资源文件中读取字符串。

资源文件的命名约定描述here

它是基于类的全名,没有程序集的名称。在我的情况下,类名为AddingLocalization.Classes.MyHelper,程序集名为AddingLocalization,因此相关的名称是Classes.MyHelper。

实际上有两种命名约定,使用点或子目录,所以我们可以调用的资源文件的

  • 一个Classes.MyHelper.resx
  • 类\ MyHelper.resx

ConfigureServices中的样板代码指定了ResourcesPath“Resources”,因此这是我们必须放置资源文件的地方。我选择了第二个选项命名的,所以我的资源文件是

  • 资源\类\ MyHelper.resx

,你可以在Solution Explorer中看到

2017-05-28_09-30-59.png

我们这样做不需要Visual Studio创建文件MyHelper.Designer.cs来访问资源,因此我们应该清除资源文件的CustomTool属性。

enter image description here

这一点很重要,因为该名称不会是有效的资源名称,将可能产生的错误信息,如果我们不关闭自定义工具。

(上定位方法(微软)一直用捏造的资源名称(例如,与underscrore而不是空间)来访问资源。新的ASP.NET核心的本地化使用原始的字符串作为资源名称。)

最后,我已经定义了一个资源字符串,如下图所示:

enter image description here

我还没有真正尝试用不同的语言(还)访问资源,但定位对象没有正确读取资源。

相关问题