如何使用参数注册通用服务

问题描述 投票:0回答:1

我有一个通用服务,我注册如下:

serviceProvider.AddSingleton(typeof(IMyService<>), typeof(MyService<>));

效果很好。它使用 T = 被注入的类来注入服务。到目前为止一切顺利。

public class MyService<T> : IMyService<T>
{
  public MyService(string myParameter)
  {
    // do something with T and myParameter.
  }
}

现在我想在注册时向构造函数传递一个参数。

如何将参数传递给通用服务?

是否存在类似下面的代码?

serviceProvider.AddSingleton(typeof(IMyService<>), typeof(MyService<>), "SomeStringValue");

如果不是,最好的解决办法是什么?

c# generics dependency-injection
1个回答
0
投票

诸如字符串和整数之类的原始值不能轻易地注册到容器中,因为它们的含义是不明确的。以下内容实际上不起作用:

// Would not really work
services.AddSingleton("SomeStringValue");
services.AddSingleton(typeof(IMyService<>), typeof(MyService<>));

但是你也不能使用开放泛型类型注册委托:

// Would certainly not really work
services.AddSingleton(typeof(IMyService<>), sp => new MyService<???("SomeStringValue"));

因此,您可以单独注册每个封闭类型:

services.AddSingleton<IMyService<A>>(new MyService<A>("SomeStringValue"));
services.AddSingleton<IMyService<B>>(new MyService<B>("SomeStringValue"));

但这可能不太方便,特别是当您有许多不同的封闭版本,或者定期添加新版本时。

在我看来,这种情况下最好的解决方案是消除字符串引起的歧义,并将该字符串包装在可以注册的包装类中:

services.AddSingleton(new MyServiceSettings("SomeStringValue"));
services.AddSingleton(typeof(IMyService<>), typeof(MyService<>));

这需要您更改

MyService<T>
的构造函数以接受
MyServiceSettings
而不是
string
:

public class MyService<T> : IMyService<T>
{
  private readonly MyServiceSettings settings;
  public MyService(MyServiceSettings settings)
  {
    this.settings = settings;
  }

  // use settings.SomeStringValue in the class
}

除了直接注入

MyServiceSettings
之外,ASP.NET Core 还允许您向构造函数提供
IOption<MyServiceSettings>
。这就是@Ralf 在评论中提到的内容。然而,正如我所见,这只会导致额外的复杂性,因为在这种情况下,您将注入一个允许访问
MyServiceSettings
参数对象的接口。这只是一个额外的间接级别,在大多数情况下是不需要的。不过,很高兴知道这个选项的存在。最好了解这些选项并了解它们的优点、缺点和后果。

© www.soinside.com 2019 - 2024. All rights reserved.