Make GetAutofacRoot return actual root Autofac lifetime scope or change method name to avoid confusion.
korifeich opened this issue · 1 comments
Is your feature request related to a problem? Please describe.
I need to get access to Root Autofac Lifetime scope to be able to begin new scope in long running task that is going to live more than existing request. In service I have access to IServiceProvider instance. In case I resolve service using this serviceProvider, I am getting parent scope disposed exception, so I decided to use root lifetime scope, to be able to avoid this kind of exception and resolve service in thread that lives longer than HTTP request thread. I've located this GetAutofaceRoot extension method and from method name it seemed to me that it is the right method to use, but it actually returns not Autofac root lifetime scope, but Lifetime scope of working service provider.
Describe the solution you'd like
I think it is better to rename this method to avoid confusion or adjust documentation to highlight this naming confusion.
Describe alternatives you've considered
I think it may be quite complicated to change name, because of others using it, so it would be nice to have extension method that gives access to the Root lifetime scope.
Here is simple example I made:
public static ILifetimeScope GetAutofacRootLifetimeScope(this ILifetimeScope scope)
{
var lifetimeScope = scope as LifetimeScope;
if (lifetimeScope == null)
{
throw new InvalidOperationException();
}
return lifetimeScope.RootLifetimeScope;
}
Like you said, we can't change the name now due to people using it.
Interestingly enough, back in .NET Core 1.0 days, I believe this actually did provide the root lifetime scope, which is why it had that name. Since then, a lot has changed inside ASP.NET Core to add concepts like IServiceProviderFactory
and so on, and we've done our best to keep the method reasonably meaningful, but, yeah, it's not necessarily what you think.
Unfortunately, we also can't really give you what you want from an IServiceProvider
. There's not really a way to "walk up the stack" and get things the way you might envision.
If you do need to access the root container during your app, our documentation does have an example of that - you have to store a reference to it yourself while in the Configure
method of startup. I'll paste that part here, but if you need more context, check out those docs.
public class Startup
{
// Omitting the other methods in the example for clarity; go
// check out the docs if you want to see everything in context.
// Here's where you might store the container. It could be static
// or maybe it's not even _in_ the Startup class, but you get the idea.
public ILifetimeScope AutofacContainer { get; private set; }
// Configure is where you add middleware. This is called after
// ConfigureContainer. You can use IApplicationBuilder.ApplicationServices
// here if you need to resolve things from the container.
public void Configure(
IApplicationBuilder app,
ILoggerFactory loggerFactory)
{
// If, for some reason, you need a reference to the built container, you
// can use the convenience extension method GetAutofacRoot.
this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
// ...and other stuff.
}
}