如何替换ASP.NET Core中的依赖项?

时间:2019-08-18 05:23:01

标签: asp.net-core dependency-injection

在startup.cs中,我们有以下内容:

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

因此我们的“索引剃刀”页面可以具有以下内容:

    public IndexModel(IStringLocalizer<Strings> localizer) {

我想将localizer包装在另一个类中,并用单个包装器替换它在IoC容器中的存在。

问题在于,在COnfigureServices方法中,似乎无法从容器中检索或删除条目。

本质上,我想替换AddLocalization调用提供的注册实例,这样就不必替换解决方案中包装类注入的每个实例。

这可能吗?

1 个答案:

答案 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>

希望有帮助!