Instead of registering the types directly, you'd need to create a factory that creates new instances in a method call.
The following sample is based on your code, but also shows some differences. In addition to the ISample implementations and the wrapper, a factory is registered in the DI container. It defines a GenerateSamples
method that uses the service provider to create new instances when called:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddTransient<ISample, SampleA>();
builder.Services.AddTransient<ISample, SampleB>();
builder.Services.AddSingleton<Wrapper>();
builder.Services.AddSingleton<SampleFactory>();
var app = builder.Build();
var wrapper = app.Services.GetRequiredService<Wrapper>();
wrapper.InstanceGenerator();
wrapper.InstanceGenerator();
class Wrapper
{
private readonly SampleFactory _factory;
public Wrapper(SampleFactory factory)
{
_factory = factory;
}
public void InstanceGenerator()
{
var samples = _factory.GenerateSamples();
foreach(var sample in samples)
Console.WriteLine($"Type: {sample.GetType().Name}, Id: {sample.InstanceId}");
}
}
class SampleFactory
{
private readonly IServiceProvider _serviceProvider;
public SampleFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IEnumerable<ISample> GenerateSamples()
{
return _serviceProvider.GetRequiredService<IEnumerable<ISample>>();
}
}
interface ISample { public Guid InstanceId { get; }}
class SampleA : ISample { public Guid InstanceId { get; set; } = Guid.NewGuid(); }
class SampleB : ISample { public Guid InstanceId { get; set; } = Guid.NewGuid(); }
If you run the sample, you can check the InstanceId
to verify that a new instance is used in the InstanceGenerator
method every time.