如何在 .NET Core 控制台应用程序中实例化 ServiceCollection 和使用 IHttpClientFactory?

How to instanciate ServiceCollection and use IHttpCientFactory in a .NET Core ConsoleApp?

我有以下代码,当 运行 这段代码时,当调用 ConfigureServices 时,我可以验证客户端是在 ConfigureService 方法中创建的。

  1. 主要问题:如何在 MainAsync 任务中获取对 clientFactory 的访问权限?
  2. 次要优先级:如何通过构造函数实例化 serviceColletion

namespace CustomeNameSpace
{
  public class Program
  {
    public static IConfigurationRoot configuration;
    private static readonly IServiceCollection serviceCollection;

    public static void Main(string[] args)
    {
      ConfigureServices();
      ILogger logger = NullLogger.Instance;
      MainAsync(logger).GetAwaiter().GetResult();
    }

    private static async Task MainAsync(ILogger log) 
    {
      // Need to use httpClientAt this location....
      // var clientFactory = .....
      // var client = clientFactory.CreateClient()
    }

    public static void ConfigureServices()
    {
      var serviceCollection = new ServiceCollection();
      serviceCollection.AddHttpClient();

      var clientFactory = serviceCollection.BuildServiceProvider().GetRequiredService<IHttpClientFactory>();
      //var client = clientFactory.CreateClient();

      configuration = new ConfigurationBuilder().SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
        .AddJsonFile("local.settings.json", false)
        .Build();
    }
  }
}

此代码需要重构以遵循更流线型的方法来应用依赖项注入。

public class Program {

    //async Task Main feature allowed from C# 7.1+
    public static async Task Main(string[] args) {
        //Composition root
        IServiceProvider services = ConfigureServices();
        
        ILogger logger = NullLogger.Instance;
        
        IHttpClientFactory clientFactory = service.GetRequiredService<IHttpClientFactory>();
        HttpClient client = clientFactory.CreateClient();
        
        IConfiguration configuration = service.GetRequiredService<IConfiguration>();
        
        await RunAsync(logger, client, configuration);
    }

    private static async Task RunAsync(ILogger log, HttpClient client, IConfiguration configuration) {
      
      //...
      
    }

    public static IServiceProvider ConfigureServices() {
        IServiceCollection services = new ServiceCollection();
        services.AddHttpClient();

        IConfigurationRoot configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
            .AddJsonFile("local.settings.json", false)
            .Build();
        services.AddSingleton<IConfigurationRoot>(configuration);
        services.AddSingleton<IConfiguration>(configuration);
        
        return services.BuildServiceProvider();
    }
}

请注意现在如何根据需要从服务提供商处解决和使用任何所需的服务。

这可以通过将主要功能封装在 class 中并从服务提供者解析它来进一步改进,这样所有显式依赖项都可以由服务容器直接解析和注入。