Here is an example similar to the one on this page.
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} ]");
}
}
And then if registered and called like this
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
services
.AddScoped<IScopedOperation1, DefaultOperation>()
.AddScoped<IScopedOperation2, DefaultOperation>()
.AddTransient<OperationLogger>())
.Build();
host.Services.GetService<OperationLogger>().LogOperations();
Once LogOperations
are called then OperationId
is different for each injected instance.
Is there a way to share the same instance in the scoped service lifetime?
CodePudding user response:
First, register DefaultOperation
as itself with scoped lifetime.
AddScoped<DefaultOperation>();
This way you will always have one object per scope. Then, register interfaces to return that object.
services.AddScoped<IScopedOperation1>(sp => sp.GetService<DefaultOperation>());
services.AddScoped<IScopedOperation2>(sp => sp.GetService<DefaultOperation>());
Here, sp
is of type IServiceProvider
, through which you can call this very container and get any service.