Is It OK to Instantiate Multiple Instances of the Generic Host (IHost)

143 Views Asked by At

We have a framework upon which my team builds microservice apps and related jobs. We want to migrate it from using IWebHost for web apps and IHost for jobs to simply using IHost for both. We haven't done so yet because of issues with DI.

Using WebHostBuilder and the Startup class, there was a way to build the services container, then use services in it to get values to bind to configuration, then rebuild the services container with the rest of the needed services. We used this technique to "early-bind" our configuration service, use it to get settings from a data store, bind those to a typed IOptions, then bind the rest of the services, thus allowing them to receive, from the DI system, the IOptions we bound.

With IHost, there is no such "double DI" and so the jobs half of our framework has needed to jury-rig things to get those settings propagated throughout the apps (we can't bind them to IOptions).

So, my goal has been to identify how to use IHost, and still be able to register a service, call that service to get settings, bind those settings to IOptions, and let them be used throughout the rest of the app. Today it occurred to me that maybe I could just create two instances of IHost in my Main() method. This solution works, but my question is are there any problems that could arise from doing this?

public static void Main(string[] args)
    {
        var tempHost = Host.CreateDefaultBuilder(args)
            .ConfigureServices(services =>
            {
                services.AddTransient<IConfigService, ConfigService>();
            })
            .Build();

        var configModel = tempHost.Services.GetRequiredService<IConfigService>().GetConfigModel();
        IConfigurationRoot? configurationRoot = null;
        tempHost.Dispose();

        var host = Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((context, builder) =>
            {
                configurationRoot = builder.AddInMemoryCollection(GetSettings(configModel)).Build();
            })
            .ConfigureServices(services =>
            {
                services.AddHostedService<MyWorker>();
                services.AddTransient<IConfigService, ConfigService>();
                services.Configure<ConfigModel>(configurationRoot);
                services.AddTransient<IGoofballService, GoofballService>();
            })
            .Build();

        host.Run();
    }

    private static Dictionary<string, string> GetSettings(ConfigModel model)
    {
        var dictionary = new Dictionary<string, string>();
        var typeName = nameof(ConfigModel);

        dictionary.Add($"{typeName}:{nameof(model.Id)}", model.Id.ToString());
        dictionary.Add($"{typeName}:{nameof(model.Stamp)}", model.Stamp.ToString(CultureInfo.InvariantCulture));

        return dictionary;
    }
0

There are 0 best solutions below