Reputation: 127
I have used this snippet to setup my application:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(Startup.Register)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
public static void Register(ContainerBuilder builder)
{
builder.RegisterType<UserService>().As<IUserServcice>().InstancePerLifetimeScope();
}
and I have utilized it in the manner mentioned below:
public interface IUserServcice
{
public long Tick { get; }
}
public class UserService : IUserServcice
{
private long _tick;
public UserService()
{
_tick = DateTime.Now.Ticks;
}
public long Tick => _tick;
}
public WeatherForecastController(IUserServcice userServcice)
{
// _logger = logger;
iUserServcice = userServcice;
var g = Startup.AutofacContainer.Resolve<IUserServcice>();
tick2 = g.Tick;
}
private async Task Get1()
{
var list = new List<long>();
list.Add(iUserServcice.Tick);
var g=Startup.AutofacContainer.Resolve<IUserServcice>();
list.Add(g.Tick);
list.Add(tick2);
//using (var scope= SorviceLocator.Container.BeginLifetimeScope("t1"))
// {
for (int i = 0; i < 3; i++)
{
await Task.Factory.StartNew(() =>
{
var sr = Startup.AutofacContainer.Resolve<IUserServcice>();
list.Add(sr.Tick);
});
}
// }
}
[HttpGet]
public async Task<IEnumerable<WeatherForecast>> Get()
{
await Get1();
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
and unfortunately the result of debug is like image uploaded below:
as you can see in the picture item in the top is the result of controller constructor injection and, other items, are inside the controller and my question is that how can I have all these items with the same value.
Upvotes: 1
Views: 363
Reputation: 23924
When you use ASP.NET Core, while you can have Autofac be the backing container, for the most part you give up working with Autofac directly when outside the Startup class. You register your stuff in Startup, but in controllers and elsewhere, it's all standard dependency injection (no Autofac references) and the Microsoft dependency injection abstraction.
This is important because it'll help you Google for answers. Don't look for "How do I do this with Autofac?" - look for "How do I do this in ASP.NET Core?"
First, avoid service location. I see what you're doing, I see what you're getting at... but the fact you need to use service location to demonstrate the issue seems like a red flag.
Now that's out of the way:
What you want is HttpContext.RequestServices
. When you have a controller, you'll have the HttpContext
and the RequestServices
object there is the request lifetime scope. It's backed by Autofac but the interface is the Microsoft interface.
You can read about RequestServices
in the Microsoft docs.
private readonly IUserService injected;
public WeatherForecastController(IUserService userService)
{
this.injected = userService;
}
public async Task Get()
{
var located = this.HttpContext.RequestServices.GetService<IUserService>();
// located and injected will be the same instance.
}
If you need to begin a child lifetime scope, again, that's an MS DI thing. You'll need an IServiceScopeFactory
. That can be a constructor dependency or you can use service location like you were doing before.
var scopeFactory = this.HttpContext.RequestServices.GetService<IServiceScopeFactory>();
using(var scope = scopeFactory.CreateScope())
{
// Now you have a scope to work with.
}
If you absolutely must get the Autofac lifetime from an IServiceProvider
for whatever reason, you can resolve one. Resolving a lifetime scope from a lifetime scope returns itself.
var requestScope = this.HttpContext.RequestServices.GetService<ILifetimeScope>();
But, again, you'll notice everything we're doing here is working with the Microsoft DI abstraction, so when you're looking for answers, I'd recommend looking more broadly and not limiting your search to Autofac. This answer is basically the same regardless of the backing container you use.
Upvotes: 2