导航

08-008 Hosting 之 ContainerMiddleware

Posted on 2015-04-07 13:03  DotNet1010  阅读(181)  评论(0)    收藏  举报

Lifekind.Scoped 一个请求一个范围是怎么实现的,由ContainerMiddleware 来解决:

Invoke 方法代码:

     public async Task Invoke(HttpContext httpContext)
        {
            if (httpContext.RequestServices != null)
            {
                throw new Exception("TODO: nested request container scope? this is probably a mistake on your part?");
            }

            using (var container = RequestServicesContainer.EnsureRequestServices(httpContext, _services))
            {
                await _next.Invoke(httpContext);
            }
        }

 EnsureRequestServices 方法 核心代码:

   return new RequestServicesContainer(httpContext, appServiceScopeFactory, appServiceProvider);

 RequestServicesContainer 构造函数代码:

      public RequestServicesContainer(
            HttpContext context,
            IServiceScopeFactory scopeFactory,
            IServiceProvider appServiceProvider)
        {
            if (scopeFactory == null)
            {
                throw new ArgumentNullException(nameof(scopeFactory));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            Context = context;
            PriorAppServices = context.ApplicationServices;
            PriorRequestServices = context.RequestServices;

            // Begin the scope
            Scope = scopeFactory.CreateScope();

            Context.ApplicationServices = appServiceProvider;
            Context.RequestServices = Scope.ServiceProvider;
        }

 看一下 扩展方法:

 public static class ContainerExtensions
    {
        public static IApplicationBuilder UseRequestServices(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<ContainerMiddleware>();
        }

        // Review: what do we use these for?

        public static IApplicationBuilder UseRequestServices(this IApplicationBuilder builder, IServiceProvider applicationServices)
        {
            // REVIEW: should this be doing fallback?
            builder.ApplicationServices = applicationServices;

            return builder.UseMiddleware<ContainerMiddleware>();
        }

        // Note: Manifests are lost after UseServices, services are flattened into ApplicationServices

        public static IApplicationBuilder UseServices(this IApplicationBuilder builder, IEnumerable<IServiceDescriptor> applicationServices)
        {
            return builder.UseServices(services => services.Add(applicationServices));
        }

        public static IApplicationBuilder UseServices(this IApplicationBuilder builder, Action<IServiceCollection> configureServices)
        {
            return builder.UseServices(serviceCollection =>
            {
                configureServices(serviceCollection);
                return serviceCollection.BuildServiceProvider();
            });
        }

        public static IApplicationBuilder UseServices(this IApplicationBuilder builder, Func<IServiceCollection, IServiceProvider> configureServices)
        {
            // Import services from hosting/KRE as fallback
            var serviceCollection = HostingServices.Create(builder.ApplicationServices);

            builder.ApplicationServices = configureServices(serviceCollection);

            return builder.UseMiddleware<ContainerMiddleware>();
        }
    }

 当调用 UseServices 方法的时候 就使用了这一中间件。

理论上应该是最靠前的一个中间件。