Ejemplo n.º 1
0
        public void CapturesServiceExceptionDetails()
        {
            var methodInfo = GetType().GetMethod(nameof(InjectedMethod), BindingFlags.NonPublic | BindingFlags.Static);
            Assert.NotNull(methodInfo);

            var services = new ServiceCollection()
                .AddSingleton<CrasherService>()
                .BuildServiceProvider();

            var applicationBuilder = new ApplicationBuilder(services);

            var builder = new ConfigureBuilder(methodInfo);
            Action<IApplicationBuilder> action = builder.Build(instance:null);
            var ex = Assert.Throws<Exception>(() => action.Invoke(applicationBuilder));

            Assert.NotNull(ex);
            Assert.Equal($"Could not resolve a service of type '{typeof(CrasherService).FullName}' for the parameter"
                + $" 'service' of method '{methodInfo.Name}' on type '{methodInfo.DeclaringType.FullName}'.", ex.Message);

            // the inner exception contains the root cause
            Assert.NotNull(ex.InnerException);
            Assert.Equal("Service instantiation failed", ex.InnerException.Message);
            Assert.Contains(nameof(CrasherService), ex.InnerException.StackTrace);
        }
Ejemplo n.º 2
0
        private void UseStartup(Type startupType, HostBuilderContext context, IServiceCollection services)
        {
            var webHostBuilderContext = GetWebHostBuilderContext(context);
            var webHostOptions        = (WebHostOptions)context.Properties[typeof(WebHostOptions)];

            ExceptionDispatchInfo startupError = null;
            object           instance          = null;
            ConfigureBuilder configureBuilder  = null;

            try
            {
                // We cannot support methods that return IServiceProvider as that is terminal and we need ConfigureServices to compose
                if (typeof(IStartup).IsAssignableFrom(startupType))
                {
                    throw new NotSupportedException($"{typeof(IStartup)} isn't supported");
                }

                instance = ActivatorUtilities.CreateInstance(new HostServiceProvider(webHostBuilderContext), startupType);
                context.Properties[_startupKey] = instance;

                // Startup.ConfigureServices
                var configureServicesBuilder = StartupLoader.FindConfigureServicesDelegate(startupType, context.HostingEnvironment.EnvironmentName);
                var configureServices        = configureServicesBuilder.Build(instance);

                configureServices(services);

                // REVIEW: We're doing this in the callback so that we have access to the hosting environment
                // Startup.ConfigureContainer
                var configureContainerBuilder = StartupLoader.FindConfigureContainerDelegate(startupType, context.HostingEnvironment.EnvironmentName);
                if (configureContainerBuilder.MethodInfo != null)
                {
                    var containerType = configureContainerBuilder.GetContainerType();
                    // Store the builder in the property bag
                    _builder.Properties[typeof(ConfigureContainerBuilder)] = configureContainerBuilder;

                    var actionType = typeof(Action <,>).MakeGenericType(typeof(HostBuilderContext), containerType);

                    // Get the private ConfigureContainer method on this type then close over the container type
                    var configureCallback = GetType().GetMethod(nameof(ConfigureContainer), BindingFlags.NonPublic | BindingFlags.Instance)
                                            .MakeGenericMethod(containerType)
                                            .CreateDelegate(actionType, this);

                    // _builder.ConfigureContainer<T>(ConfigureContainer);
                    typeof(IHostBuilder).GetMethods().First(m => m.Name == nameof(IHostBuilder.ConfigureContainer))
                    .MakeGenericMethod(containerType)
                    .Invoke(_builder, new object[] { configureCallback });
                }

                // Resolve Configure after calling ConfigureServices and ConfigureContainer
                configureBuilder = StartupLoader.FindConfigureDelegate(startupType, context.HostingEnvironment.EnvironmentName);
            }
            catch (Exception ex) when(webHostOptions.CaptureStartupErrors)
            {
                startupError = ExceptionDispatchInfo.Capture(ex);
            }

            // Startup.Configure
            services.Configure <GenericWebHostServiceOptions>(options =>
            {
                options.ConfigureApplication = app =>
                {
                    // Throw if there was any errors initializing startup
                    startupError?.Throw();

                    // Execute Startup.Configure
                    if (instance != null && configureBuilder != null)
                    {
                        configureBuilder.Build(instance)(app);
                    }
                };
            });
        }