/// <summary> /// Creates a new isolated application builder which gets its own <see cref="ServiceCollection"/>, which only /// has the default services registered. It will not share the <see cref="ServiceCollection"/> from the /// originating app. /// </summary> /// <param name="app">The application builder to create the isolated app from.</param> /// <param name="configuration">The branch of the isolated app.</param> /// <param name="registration">A method to configure the newly created service collection.</param> /// <returns>The new pipeline with the isolated application integrated.</returns> public static IApplicationBuilder Isolate( this IApplicationBuilder app, Action <IApplicationBuilder> configuration, Func <IServiceCollection, IServiceProvider> registration) { var services = CreateDefaultServiceCollection(app.ApplicationServices); var provider = registration(services); var builder = new ApplicationBuilder(null); builder.ApplicationServices = provider; builder.Use(async(context, next) => { var factory = provider.GetRequiredService <IServiceScopeFactory>(); // Store the original request services in the current ASP.NET context. context.Items[typeof(IServiceProvider)] = context.RequestServices; try { using (var scope = factory.CreateScope()) { context.RequestServices = scope.ServiceProvider; await next(); } } finally { context.RequestServices = null; } }); configuration(builder); return(app.Use(next => { // Run the rest of the pipeline in the original context, // with the services defined by the parent application builder. builder.Run(async context => { var factory = app.ApplicationServices.GetRequiredService <IServiceScopeFactory>(); try { using (var scope = factory.CreateScope()) { context.RequestServices = scope.ServiceProvider; await next(context); } } finally { context.RequestServices = null; } }); var branch = builder.Build(); return context => branch(context); })); }