Пример #1
0
        /// <summary>
        /// Specify the startup type to be used by the web host.
        /// </summary>
        /// <param name="hostBuilder">The <see cref="IWebHostBuilder"/> to configure.</param>
        /// <param name="startupType">The <see cref="Type"/> to be used.</param>
        /// <returns>The <see cref="IWebHostBuilder"/>.</returns>
        public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType)
        {
            var startupAssemblyName = startupType.GetTypeInfo().Assembly.GetName().Name;

            return(hostBuilder.UseSetting(WebHostDefaults.ApplicationKey, startupAssemblyName)
                   .ConfigureServices(services =>
            {
                if (typeof(IStartup).GetTypeInfo().IsAssignableFrom(startupType.GetTypeInfo()))
                {
                    services.AddSingleton(typeof(IStartup), startupType);
                }
                else
                {
                    services.AddSingleton(typeof(IStartup), sp =>
                    {
                        var hostingEnvironment = sp.GetRequiredService <IHostingEnvironment>();
                        return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName));
                    });
                }
            }));
        }
Пример #2
0
        public static IWebHostBuilder UseStartup <[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TStartup>(this IWebHostBuilder hostBuilder, Func <WebHostBuilderContext, TStartup> startupFactory) where TStartup : class
        {
            if (startupFactory == null)
            {
                throw new ArgumentNullException(nameof(startupFactory));
            }

            var startupAssemblyName = startupFactory.GetMethodInfo().DeclaringType !.Assembly.GetName().Name;

            hostBuilder.UseSetting(WebHostDefaults.ApplicationKey, startupAssemblyName);

            // Light up the GenericWebHostBuilder implementation
            if (hostBuilder is ISupportsStartup supportsStartup)
            {
                return(supportsStartup.UseStartup(startupFactory));
            }

            return(hostBuilder
                   .ConfigureServices((context, services) =>
            {
                services.AddSingleton(typeof(IStartup), sp =>
                {
                    var instance = startupFactory(context) ?? throw new InvalidOperationException("The specified factory returned null startup instance.");

                    var hostingEnvironment = sp.GetRequiredService <IHostEnvironment>();

                    // Check if the instance implements IStartup before wrapping
                    if (instance is IStartup startup)
                    {
                        return startup;
                    }

                    return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, instance.GetType(), hostingEnvironment.EnvironmentName, instance));
                });
            }));
        }
Пример #3
0
        private IServiceCollection BuildCommonServices(out AggregateException hostingStartupErrors)
        {
            hostingStartupErrors = null;

            _options = new WebHostOptions(_config, Assembly.GetEntryAssembly()?.GetName().Name);

            if (!_options.PreventHostingStartup)
            {
                var exceptions = new List <Exception>();

                // Execute the hosting startup assemblies
                foreach (var assemblyName in _options.GetFinalHostingStartupAssemblies().Distinct(StringComparer.OrdinalIgnoreCase))
                {
                    try
                    {
                        var assembly = Assembly.Load(new AssemblyName(assemblyName));

                        foreach (var attribute in assembly.GetCustomAttributes <HostingStartupAttribute>())
                        {
                            var hostingStartup = (IHostingStartup)Activator.CreateInstance(attribute.HostingStartupType);
                            hostingStartup.Configure(this);
                        }
                    }
                    catch (Exception ex)
                    {
                        // Capture any errors that happen during startup
                        exceptions.Add(new InvalidOperationException($"Startup assembly {assemblyName} failed to execute. See the inner exception for more details.", ex));
                    }
                }

                if (exceptions.Count > 0)
                {
                    hostingStartupErrors = new AggregateException(exceptions);
                }
            }

            var contentRootPath = ResolveContentRootPath(_options.ContentRootPath, AppContext.BaseDirectory);

            // Initialize the hosting environment
            _hostingEnvironment.Initialize(contentRootPath, _options);
            _context.HostingEnvironment = _hostingEnvironment;

            var services = new ServiceCollection();

            services.AddSingleton(_options);
            services.AddSingleton <IHostingEnvironment>(_hostingEnvironment);
            services.AddSingleton <Extensions.Hosting.IHostingEnvironment>(_hostingEnvironment);
            services.AddSingleton(_context);

            var builder = new ConfigurationBuilder()
                          .SetBasePath(_hostingEnvironment.ContentRootPath)
                          .AddConfiguration(_config);

            _configureAppConfigurationBuilder?.Invoke(_context, builder);

            var configuration = builder.Build();

            services.AddSingleton <IConfiguration>(configuration);
            _context.Configuration = configuration;

            var listener = new DiagnosticListener("Microsoft.AspNetCore");

            services.AddSingleton <DiagnosticListener>(listener);
            services.AddSingleton <DiagnosticSource>(listener);

            services.AddTransient <IApplicationBuilderFactory, ApplicationBuilderFactory>();
            services.AddTransient <IHttpContextFactory, HttpContextFactory>();
            services.AddScoped <IMiddlewareFactory, MiddlewareFactory>();
            services.AddOptions();
            services.AddLogging();

            // Conjure up a RequestServices
            services.AddTransient <IStartupFilter, AutoRequestServicesStartupFilter>();
            services.AddTransient <IServiceProviderFactory <IServiceCollection>, DefaultServiceProviderFactory>();

            // Ensure object pooling is available everywhere.
            services.AddSingleton <ObjectPoolProvider, DefaultObjectPoolProvider>();

            if (!string.IsNullOrEmpty(_options.StartupAssembly))
            {
                try
                {
                    var startupType = StartupLoader.FindStartupType(_options.StartupAssembly, _hostingEnvironment.EnvironmentName);

                    if (typeof(IStartup).GetTypeInfo().IsAssignableFrom(startupType.GetTypeInfo()))
                    {
                        services.AddSingleton(typeof(IStartup), startupType);
                    }
                    else
                    {
                        services.AddSingleton(typeof(IStartup), sp =>
                        {
                            var hostingEnvironment = sp.GetRequiredService <IHostingEnvironment>();
                            var methods            = StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName);
                            return(new ConventionBasedStartup(methods));
                        });
                    }
                }
                catch (Exception ex)
                {
                    var capture = ExceptionDispatchInfo.Capture(ex);
                    services.AddSingleton <IStartup>(_ =>
                    {
                        capture.Throw();
                        return(null);
                    });
                }
            }

            _configureServices?.Invoke(_context, services);

            return(services);
        }
Пример #4
0
        private IServiceCollection BuildHostingServices()
        {
            _options = new WebHostOptions(_config);

            var appEnvironment  = PlatformServices.Default.Application;
            var contentRootPath = ResolveContentRootPath(_options.ContentRootPath, appEnvironment.ApplicationBasePath);
            var applicationName = _options.ApplicationName ?? appEnvironment.ApplicationName;

            // Initialize the hosting environment
            _hostingEnvironment.Initialize(applicationName, contentRootPath, _options);

            var services = new ServiceCollection();

            services.AddSingleton(_hostingEnvironment);

            if (_loggerFactory == null)
            {
                _loggerFactory = new LoggerFactory();
            }

            foreach (var configureLogging in _configureLoggingDelegates)
            {
                configureLogging(_loggerFactory);
            }

            //The configured ILoggerFactory is added as a singleton here. AddLogging below will not add an additional one.
            services.AddSingleton(_loggerFactory);

            //This is required to add ILogger of T.
            services.AddLogging();

            services.AddTransient <IApplicationBuilderFactory, ApplicationBuilderFactory>();
            services.AddTransient <IHttpContextFactory, HttpContextFactory>();
            services.AddOptions();

            var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");

            services.AddSingleton <DiagnosticSource>(diagnosticSource);
            services.AddSingleton <DiagnosticListener>(diagnosticSource);

            // Conjure up a RequestServices
            services.AddTransient <IStartupFilter, AutoRequestServicesStartupFilter>();

            // Ensure object pooling is available everywhere.
            services.AddSingleton <ObjectPoolProvider, DefaultObjectPoolProvider>();

            if (!string.IsNullOrEmpty(_options.ServerAssembly))
            {
                // Add the server
                try
                {
                    var serverType = ServerLoader.ResolveServerType(_options.ServerAssembly);
                    services.AddSingleton(typeof(IServer), serverType);
                }
                catch (Exception ex)
                {
                    var capture = ExceptionDispatchInfo.Capture(ex);
                    services.AddSingleton <IServer>(_ =>
                    {
                        capture.Throw();
                        return(null);
                    });
                }
            }

            if (!string.IsNullOrEmpty(_options.StartupAssembly))
            {
                try
                {
                    var startupType = StartupLoader.FindStartupType(_options.StartupAssembly, _hostingEnvironment.EnvironmentName);

                    if (typeof(IStartup).GetTypeInfo().IsAssignableFrom(startupType.GetTypeInfo()))
                    {
                        services.AddSingleton(typeof(IStartup), startupType);
                    }
                    else
                    {
                        services.AddSingleton(typeof(IStartup), sp =>
                        {
                            var hostingEnvironment = sp.GetRequiredService <IHostingEnvironment>();
                            var methods            = StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName);
                            return(new ConventionBasedStartup(methods));
                        });
                    }
                }
                catch (Exception ex)
                {
                    var capture = ExceptionDispatchInfo.Capture(ex);
                    services.AddSingleton <IStartup>(_ =>
                    {
                        capture.Throw();
                        return(null);
                    });
                }
            }

            foreach (var configureServices in _configureServicesDelegates)
            {
                configureServices(services);
            }

            return(services);
        }
Пример #5
0
        private IServiceCollection BuildCommonServices(out AggregateException?hostingStartupErrors)
        {
            hostingStartupErrors = null;

            _options = new WebHostOptions(_config, Assembly.GetEntryAssembly()?.GetName().Name ?? string.Empty);

            if (!_options.PreventHostingStartup)
            {
                var exceptions = new List <Exception>();
                var processed  = new HashSet <Assembly>();

                // Execute the hosting startup assemblies
                foreach (var assemblyName in _options.GetFinalHostingStartupAssemblies())
                {
                    try
                    {
                        var assembly = Assembly.Load(new AssemblyName(assemblyName));

                        if (!processed.Add(assembly))
                        {
                            // Already processed, skip it
                            continue;
                        }

                        foreach (var attribute in assembly.GetCustomAttributes <HostingStartupAttribute>())
                        {
                            var hostingStartup = (IHostingStartup)Activator.CreateInstance(attribute.HostingStartupType) !;
                            hostingStartup.Configure(this);
                        }
                    }
                    catch (Exception ex)
                    {
                        // Capture any errors that happen during startup
                        exceptions.Add(new InvalidOperationException($"Startup assembly {assemblyName} failed to execute. See the inner exception for more details.", ex));
                    }
                }

                if (exceptions.Count > 0)
                {
                    hostingStartupErrors = new AggregateException(exceptions);
                }
            }

            var contentRootPath = ResolveContentRootPath(_options.ContentRootPath, AppContext.BaseDirectory);

            // Initialize the hosting environment
            ((IWebHostEnvironment)_hostingEnvironment).Initialize(contentRootPath, _options);
            _context.HostingEnvironment = _hostingEnvironment;

            var services = new ServiceCollection();

            services.AddSingleton(_options);
            services.AddSingleton <IWebHostEnvironment>(_hostingEnvironment);
            services.AddSingleton <IHostEnvironment>(_hostingEnvironment);
#pragma warning disable CS0618 // Type or member is obsolete
            services.AddSingleton <AspNetCore.Hosting.IHostingEnvironment>(_hostingEnvironment);
            services.AddSingleton <Extensions.Hosting.IHostingEnvironment>(_hostingEnvironment);
#pragma warning restore CS0618 // Type or member is obsolete
            services.AddSingleton(_context);

            var builder = new ConfigurationBuilder()
                          .SetBasePath(_hostingEnvironment.ContentRootPath)
                          .AddConfiguration(_config, shouldDisposeConfiguration: true);

            _configureAppConfigurationBuilder?.Invoke(_context, builder);

            var configuration = builder.Build();
            // register configuration as factory to make it dispose with the service provider
            services.AddSingleton <IConfiguration>(_ => configuration);
            _context.Configuration = configuration;

            services.TryAddSingleton(sp => new DiagnosticListener("Microsoft.AspNetCore"));
            services.TryAddSingleton <DiagnosticSource>(sp => sp.GetRequiredService <DiagnosticListener>());
            services.TryAddSingleton(sp => new ActivitySource("Microsoft.AspNetCore"));

            services.AddTransient <IApplicationBuilderFactory, ApplicationBuilderFactory>();
            services.AddTransient <IHttpContextFactory, DefaultHttpContextFactory>();
            services.AddScoped <IMiddlewareFactory, MiddlewareFactory>();
            services.AddOptions();
            services.AddLogging();

            services.AddTransient <IServiceProviderFactory <IServiceCollection>, DefaultServiceProviderFactory>();

            if (!string.IsNullOrEmpty(_options.StartupAssembly))
            {
                try
                {
                    var startupType = StartupLoader.FindStartupType(_options.StartupAssembly, _hostingEnvironment.EnvironmentName);

                    if (typeof(IStartup).IsAssignableFrom(startupType))
                    {
                        services.AddSingleton(typeof(IStartup), startupType);
                    }
                    else
                    {
                        services.AddSingleton(typeof(IStartup), sp =>
                        {
                            var hostingEnvironment = sp.GetRequiredService <IHostEnvironment>();
                            var methods            = StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName);
                            return(new ConventionBasedStartup(methods));
                        });
                    }
                }
                catch (Exception ex)
                {
                    var capture = ExceptionDispatchInfo.Capture(ex);
                    services.AddSingleton <IStartup>(_ =>
                    {
                        capture.Throw();
                        return(null);
                    });
                }
            }

            _configureServices?.Invoke(_context, services);

            return(services);
        }
Пример #6
0
        public GenericWebHostBuilder(IHostBuilder builder, WebHostBuilderOptions options)
        {
            _builder = builder;
            var configBuilder = new ConfigurationBuilder()
                                .AddInMemoryCollection();

            if (!options.SuppressEnvironmentConfiguration)
            {
                configBuilder.AddEnvironmentVariables(prefix: "ASPNETCORE_");
            }

            _config = configBuilder.Build();

            _builder.ConfigureHostConfiguration(config =>
            {
                config.AddConfiguration(_config);

                // We do this super early but still late enough that we can process the configuration
                // wired up by calls to UseSetting
                ExecuteHostingStartups();
            });

            // IHostingStartup needs to be executed before any direct methods on the builder
            // so register these callbacks first
            _builder.ConfigureAppConfiguration((context, configurationBuilder) =>
            {
                if (_hostingStartupWebHostBuilder != null)
                {
                    var webhostContext = GetWebHostBuilderContext(context);
                    _hostingStartupWebHostBuilder.ConfigureAppConfiguration(webhostContext, configurationBuilder);
                }
            });

            _builder.ConfigureServices((context, services) =>
            {
                var webhostContext = GetWebHostBuilderContext(context);
                var webHostOptions = (WebHostOptions)context.Properties[typeof(WebHostOptions)];

                // Add the IHostingEnvironment and IApplicationLifetime from Microsoft.AspNetCore.Hosting
                services.AddSingleton(webhostContext.HostingEnvironment);
#pragma warning disable CS0618 // Type or member is obsolete
                services.AddSingleton((AspNetCore.Hosting.IHostingEnvironment)webhostContext.HostingEnvironment);
                services.AddSingleton <IApplicationLifetime, GenericWebHostApplicationLifetime>();
#pragma warning restore CS0618 // Type or member is obsolete

                services.Configure <GenericWebHostServiceOptions>(options =>
                {
                    // Set the options
                    options.WebHostOptions = webHostOptions;
                    // Store and forward any startup errors
                    options.HostingStartupExceptions = _hostingStartupErrors;
                });

                // REVIEW: This is bad since we don't own this type. Anybody could add one of these and it would mess things up
                // We need to flow this differently
                var listener = new DiagnosticListener("Microsoft.AspNetCore");
                services.TryAddSingleton <DiagnosticListener>(listener);
                services.TryAddSingleton <DiagnosticSource>(listener);

                services.TryAddSingleton <IHttpContextFactory, DefaultHttpContextFactory>();
                services.TryAddScoped <IMiddlewareFactory, MiddlewareFactory>();
                services.TryAddSingleton <IApplicationBuilderFactory, ApplicationBuilderFactory>();

                // IMPORTANT: This needs to run *before* direct calls on the builder (like UseStartup)
                _hostingStartupWebHostBuilder?.ConfigureServices(webhostContext, services);

                // Support UseStartup(assemblyName)
                if (!string.IsNullOrEmpty(webHostOptions.StartupAssembly))
                {
                    try
                    {
                        var startupType = StartupLoader.FindStartupType(webHostOptions.StartupAssembly, webhostContext.HostingEnvironment.EnvironmentName);
                        UseStartup(startupType, context, services);
                    }
                    catch (Exception ex) when(webHostOptions.CaptureStartupErrors)
                    {
                        var capture = ExceptionDispatchInfo.Capture(ex);

                        services.Configure <GenericWebHostServiceOptions>(options =>
                        {
                            options.ConfigureApplication = app =>
                            {
                                // Throw if there was any errors initializing startup
                                capture.Throw();
                            };
                        });
                    }
                }
            });
        }
Пример #7
0
        private void UseStartup([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Type startupType, HostBuilderContext context, IServiceCollection services, object?instance = null)
        {
            var webHostBuilderContext = GetWebHostBuilderContext(context);
            var webHostOptions        = (WebHostOptions)context.Properties[typeof(WebHostOptions)];

            ExceptionDispatchInfo?startupError     = 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");
                }
                if (StartupLoader.HasConfigureServicesIServiceProviderDelegate(startupType, context.HostingEnvironment.EnvironmentName))
                {
                    throw new NotSupportedException($"ConfigureServices returning an {typeof(IServiceProvider)} 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 = typeof(GenericWebHostBuilder).GetMethod(nameof(ConfigureContainerImpl), BindingFlags.NonPublic | BindingFlags.Instance) !
                                            .MakeGenericMethod(containerType)
                                            .CreateDelegate(actionType, this);

                    // _builder.ConfigureContainer<T>(ConfigureContainer);
                    typeof(IHostBuilder).GetMethod(nameof(IHostBuilder.ConfigureContainer)) !
                    .MakeGenericMethod(containerType)
                    .InvokeWithoutWrappingExceptions(_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);
                    }
                };
            });
        }