public void NoSpecialEntryPointPatternHostBuilderConfigureHostBuilderCallbackIsCalled() { bool called = false; void ConfigureHostBuilder(object hostBuilder) { Assert.IsAssignableFrom <IHostBuilder>(hostBuilder); called = true; } var factory = HostFactoryResolver.ResolveHostFactory(typeof(NoSpecialEntryPointPattern.Program).Assembly, waitTimeout: s_WaitTimeout, configureHostBuilder: ConfigureHostBuilder); Assert.NotNull(factory); Assert.IsAssignableFrom <IHost>(factory(Array.Empty <string>())); Assert.True(called); }
public void NoSpecialEntryPointPatternBuildsThenThrowsCallsEntryPointCompletedCallbackWithException() { var wait = new ManualResetEventSlim(false); Exception?entryPointException = null; void EntryPointCompleted(Exception?exception) { entryPointException = exception; wait.Set(); } var factory = HostFactoryResolver.ResolveHostFactory(typeof(NoSpecialEntryPointPatternBuildsThenThrows.Program).Assembly, waitTimeout: s_WaitTimeout, stopApplication: false, entrypointCompleted: EntryPointCompleted); Assert.NotNull(factory); Assert.IsAssignableFrom <IHost>(factory(Array.Empty <string>())); Assert.True(wait.Wait(s_WaitTimeout)); Assert.NotNull(entryPointException); }
internal static IServiceProvider GetServiceProviderWithHostFactoryResolver(Assembly assembly) { #if NETCOREAPP2_1 || NETFRAMEWORK return(null); #else // We're disabling the default server and the console host lifetime. This will disable: // 1. Listening on ports // 2. Logging to the console from the default host. // This is essentially what the test server does in order to get access to the application's // IServicerProvider *and* middleware pipeline. void ConfigureHostBuilder(object hostBuilder) { ((IHostBuilder)hostBuilder).ConfigureServices((context, services) => { services.AddSingleton <IServer, NoopServer>(); services.AddSingleton <IHostLifetime, NoopHostLifetime>(); }); } var waitForStartTcs = new TaskCompletionSource <object>(); void OnEntryPointExit(Exception exception) { // If the entry point exited, we'll try to complete the wait if (exception != null) { waitForStartTcs.TrySetException(exception); } else { waitForStartTcs.TrySetResult(null); } } // If all of the existing techniques fail, then try to resolve the ResolveHostFactory var factory = HostFactoryResolver.ResolveHostFactory(assembly, stopApplication: false, configureHostBuilder: ConfigureHostBuilder, entrypointCompleted: OnEntryPointExit); // We're unable to resolve the factory. This could mean the application wasn't referencing the right // version of hosting. if (factory == null) { return(null); } try { // Get the IServiceProvider from the host #if NET6_0_OR_GREATER var assemblyName = assembly.GetName()?.FullName ?? string.Empty; // We should set the application name to the startup assembly to avoid falling back to the entry assembly. var services = ((IHost)factory(new[] { $"--{HostDefaults.ApplicationKey}={assemblyName}" })).Services; #else var services = ((IHost)factory(Array.Empty <string>())).Services; #endif // Wait for the application to start so that we know it's fully configured. This is important because // we need the middleware pipeline to be configured before we access the ISwaggerProvider in // in the IServiceProvider var applicationLifetime = services.GetRequiredService <IHostApplicationLifetime>(); using (var registration = applicationLifetime.ApplicationStarted.Register(() => waitForStartTcs.TrySetResult(null))) { waitForStartTcs.Task.Wait(); return(services); } } catch (InvalidOperationException) { // We're unable to resolve the host, swallow the exception and return null } return(null); #endif }