如何在作用域服务生命周期内与多个接口共享同一个实例

dra*_*zen 3 c# dependency-injection .net-core asp.net-core-6.0

这是与本页上的示例类似的示例。

public interface IOperation
{
  string OperationId { get; }
}

public interface IScopedOperation1 : IOperation { }

public interface IScopedOperation2 : IOperation { }

public class DefaultOperation : IScopedOperation1, IScopedOperation2
{
   public string OperationId { get; } = Guid.NewGuid().ToString()[^4..];
}

public class OperationLogger
{
  private readonly IScopedOperation1 _scopedOperation1;
  private readonly IScopedOperation2 _scopedOperation2;

  public OperationLogger(
      IScopedOperation1 op1, IScopedOperation2 op2) =>
      (_scopedOperation1, _scopedOperation2) = (op1, op2);

  public void LogOperations()
  {
     Console.WriteLine($"Operation1: [ {_scopedOperation1.OperationId} ]");
     Console.WriteLine($"Operation2: [ {_scopedOperation2.OperationId} ]");
  }
}
Run Code Online (Sandbox Code Playgroud)

然后如果像这样注册和调用

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((_, services) =>
        services
         .AddScoped<IScopedOperation1, DefaultOperation>()
         .AddScoped<IScopedOperation2, DefaultOperation>()
         .AddTransient<OperationLogger>())
    .Build();

host.Services.GetService<OperationLogger>().LogOperations();
Run Code Online (Sandbox Code Playgroud)

一旦LogOperations被调用,OperationId每个注入的实例都是不同的。

有没有办法在作用域服务生命周期内共享同一个实例?

Dmi*_*tov 10

首先,DefaultOperation使用范围生命周期注册为自身。

AddScoped<DefaultOperation>();
Run Code Online (Sandbox Code Playgroud)

这样,每个作用域将始终拥有一个对象。然后,注册接口以返回该对象。

services.AddScoped<IScopedOperation1>(sp => sp.GetService<DefaultOperation>());
services.AddScoped<IScopedOperation2>(sp => sp.GetService<DefaultOperation>());
Run Code Online (Sandbox Code Playgroud)

这里,sp是 类型IServiceProvider,通过它你可以调用这个容器并获得任何服务。