在startup.cs中,我们有以下内容:
public void ConfigureServices(IServiceCollection services)
{
services.AddLocalization(options => options.ResourcesPath = "Resources");
}
因此我们的“索引剃刀”页面可以具有以下内容:
public IndexModel(IStringLocalizer<Strings> localizer) {
我想将localizer
包装在另一个类中,并用单个包装器替换它在IoC容器中的存在。
问题在于,在COnfigureServices
方法中,似乎无法从容器中检索或删除条目。
本质上,我想替换AddLocalization
调用提供的注册实例,这样就不必替换解决方案中包装类注入的每个实例。
这可能吗?
答案 0 :(得分:1)
您可以使用装饰器模式解决此问题。
首先,配置服务,以便您可以直接访问StringLocalizer<>
。这是针对MyLocalizer<>
类的,因为它需要StringLocalizer<>
类型的直接实例,而不是接口(IStringLocalizer<>
)。如果您不注册,MyLocalizer<>
将无法解决。
services.AddTransient(typeof(StringLocalizer<>));
然后注册装饰器(要替换的依赖项)。 请注意,我假设在此代码行之前调用了AddLocalization()
。这是DI容器的规则;它总是解析最后的注册类型。因此,在这一行代码之后,IStringLocalizer<>
的所有从属都将得到MyLocalizer<>
而不是标准的StringLocalizer<>
。
// be careful about using Singleton scope
services.AddSingleton(typeof(IStringLocalizer<>), typeof(MyLocalizer<>));
装饰器实施:
装饰器模式允许您向现有对象添加额外的功能。假设IStringLocalizer<T>
对象返回一个简单的字符串,只需要将其大写即可。
public class MyLocalizer<T> : IStringLocalizer<T>
{
public MyLocalizer(StringLocalizer<T> original)
{
_original = original;
}
private readonly StringLocalizer<T> _original;
// the decorator behavior is the same for all other methods.
// But for this particular method it adds a little feature to the original one! Beautiful :)
public LocalizedString this[string name] =>
new LocalizedString(name, _original[name].Value.ToUpper());
public LocalizedString this[string name, params object[] arguments] =>
_original[name, arguments];
public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures) =>
_original.GetAllStrings(includeParentCultures);
public IStringLocalizer WithCulture(CultureInfo culture) =>
_original.WithCulture(culture);
}
现在,您的依赖类中的任何内容都不会改变。他们只使用MyLocalizer<T>
而不是MVC的StingLocalizer<T>
。
希望有帮助!