Using Autofac in ASP.NET along with the ContainerDisposalModule, how can i support fire and forget calls that have component dependencies that need to be resolved? The prob
Answer posted by Alex adapted to current Autofac and MVC versions:
InstancePerRequest
for a database contextILifetimeScope
as dependency to get to the containerSingleInstance
ensures it's the root lifetime scopeHostingEnvironment.QueueBackgroundWorkItem
to reliably run something in the backgroundMatchingScopeLifetimeTags.RequestLifetimeScopeTag
to avoid having to know the tagname autofac uses for PerRequest lifetimeshttps://groups.google.com/forum/#!topic/autofac/gJYDDls981A https://groups.google.com/forum/#!topic/autofac/yGQWjVbPYGM
Gist: https://gist.github.com/janv8000/35e6250c8efc00288d21
Global.asax.cs:
protected void Application_Start() {
//Other registrations
builder.RegisterType();
builder.RegisterType().As().InstancePerRequest(); //WebsiteContext is a EF DbContext
builder.RegisterType().As().SingleInstance();
}
AsyncRunner.cs
public interface IAsyncRunner
{
void Run(Action action);
}
public class AsyncRunner : IAsyncRunner
{
public ILifetimeScope LifetimeScope { get; set; }
public AsyncRunner(ILifetimeScope lifetimeScope)
{
Guard.NotNull(() => lifetimeScope, lifetimeScope);
LifetimeScope = lifetimeScope;
}
public void Run(Action action)
{
HostingEnvironment.QueueBackgroundWorkItem(ct =>
{
// Create a nested container which will use the same dependency
// registrations as set for HTTP request scopes.
using (var container = LifetimeScope.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag))
{
var service = container.Resolve();
action(service);
}
});
}
}
Controller
public Controller(IAsyncRunner asyncRunner)
{
Guard.NotNull(() => asyncRunner, asyncRunner);
AsyncRunner = asyncRunner;
}
public ActionResult Index()
{
//Snip
AsyncRunner.Run(listingService => listingService.RenderListing(listingGenerationArguments, Thread.CurrentThread.CurrentCulture));
//Snip
}
ListingService
public class ListingService : IListingService
{
public ListingService(IWebsiteContext context)
{
Guard.NotNull(() => context, context);
Context = context;
}
}