AddSingleton(S, T) 代替 AddSingleton(T) 的好处

Joe*_*R94 0 c# asp.net-core blazor

使用services.AddSingleton<SomeService, SomeServiceImplementation>()而不是有services.AddSingleton<SomeServiceImplementation>()什么好处?

例如我有一个示例界面

interface ISampleInterface
{
   void DoSomething();
}
Run Code Online (Sandbox Code Playgroud)

和一个样本类:

class SampleClass : ISampleInterface
{
  public void DoSomething()
  {
    console.write("hi");
  }
}
Run Code Online (Sandbox Code Playgroud)

不,我做 services.AddSingleton<SampleClass>()

为什么或何时使用services.AddSingleton<ISampleInterface, SampleClass>()

谢谢你的帮助!:-)

Pan*_*vos 9

services.AddSingleton<SampleInterface, SampleClass>() 允许您为同一接口注册不同的实现,而无需修改其余代码。

以最少的努力更改实现

假设您有一个ILogger接口和实现,例如记录到浏览器的控制台或将日志条目发送到不同的服务,例如ConsoleLogger,MyServiceLoggerPrometheusLogger。如果您只注册了实现,例如services.AddSingleton<ConsoleLogger>(),每次更改记录器实现时,您都必须更改所有类。

您必须转到每个页面并进行更改

@inject ConsoleLogger logger;
Run Code Online (Sandbox Code Playgroud)

@inject MyServiceLogger logger;
Run Code Online (Sandbox Code Playgroud)

忘记在运行时也指定记录器。每次想要使用新的日志服务时,都必须部署应用程序。

通过注册接口和特定实现,您的所有类都可以继续使用ILogger<T>并且永远不会知道实现已更改。

运行时的实现选择

您甚至可以根据环境变量、配置或您想要的任何其他逻辑在运行时更改实现,例如:

if (app.IsDevelopment)
{
    services.AddSingleton<ILogger,ConsoleLogger>();
}
else
{
    services.AddSingleton<ILogger,MyServiceLogger>();
}
Run Code Online (Sandbox Code Playgroud)

单元测试

在单元测试中,您可以使用空记录器 - 事实上,出于这个原因,Logging 中间件在核心 Abstractions 包中有一个NullLogger类。

或者您可以将测试框架的输出方法包装到一个ILogger实现中并使用它,而无需修改代码。例如,xUnit 为此使用ITestOutputHelper接口。您可以创建一个XUnitlogger将调用转发到此接口的:

public class XUnitLogger:ILogger
{
   private readonly ITestOutputHelper _output;
   public XUnitLogger(ITestOutputHelper output)
   {
       _output=output;
   }
   ...
   void Log(...)
   {
       _output.WriteLine(...);
   }
}
Run Code Online (Sandbox Code Playgroud)