pcut_uwp/PCUT/Http.Core/HttpClientFactory.cs

133 lines
4.3 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
namespace Http.Core
{
public class HttpClientFactory : IDisposable
{
private HttpClientFactory() { }
private static readonly object _instanceLock = new object();
private static HttpClientFactory _instance;
public static HttpClientFactory Instance
{
get
{
if (_instance == null)
{
lock (_instanceLock)
{
if (_instance == null)
_instance = new HttpClientFactory();
}
}
return _instance;
}
}
public void Dispose()
{
foreach (var config in _configs)
{
config.Value.Dispose();
}
_configs.Clear();
}
private readonly ConcurrentDictionary<string, HttpClientConfig> _configs = new ConcurrentDictionary<string, HttpClientConfig>();
public delegate void ConfigureBuilder(HttpClientBuilder builder);
public static HttpClientBuilder AddHttpClient(string name)
{
var builder = new HttpClientBuilder();
_ = Instance._configs.TryAdd(name, builder.Config);
return builder;
}
public static HttpClient CreateClient(string name)
{
if (!Instance._configs.ContainsKey(name))
_ = Instance._configs.TryAdd(name, new HttpClientConfig());
var config = Instance._configs[name];
var client = new HttpClient(config.Handler, false);
config.ConfigureClient?.Invoke(client);
return client;
}
public delegate void ConfigureClient(HttpClient client);
public delegate DelegatingHandler HandlerFactory();
public class HttpClientBuilder
{
internal HttpClientConfig Config { get; } = new HttpClientConfig();
public HttpClientBuilder AddConfigureClient(ConfigureClient configureClient)
{
Config.ConfigureClient += configureClient;
return this;
}
public HttpClientBuilder AddHttpMessageHandler(HandlerFactory configureHandler)
{
Config.HandlerFactories.Add(configureHandler);
return this;
}
}
internal class HttpClientConfig : IDisposable
{
internal ConfigureClient ConfigureClient { get; set; }
internal ICollection<HandlerFactory> HandlerFactories { get; private set; }
internal HttpClientConfig()
{
HandlerFactories = new List<HandlerFactory>();
}
private readonly object _handlerLock = new object();
private HttpMessageHandler _handler;
internal HttpMessageHandler Handler
{
get
{
if (_handler == null)
{
lock (_handlerLock)
{
if (_handler == null)
_handler = BuildHandler();
}
}
return _handler;
}
}
private HttpMessageHandler BuildHandler()
{
if (HandlerFactories == null || !HandlerFactories.Any())
return new HttpClientHandler();
DelegatingHandler handler, intermediate;
handler = intermediate = HandlerFactories.First().Invoke();
foreach (var handlerFactory in HandlerFactories.Skip(1))
{
intermediate.InnerHandler = handlerFactory();
intermediate = intermediate.InnerHandler as DelegatingHandler;
}
intermediate.InnerHandler = new HttpClientHandler();
return handler;
}
public void Dispose()
{
ConfigureClient = null;
HandlerFactories?.Clear();
HandlerFactories = null;
_handler?.Dispose();
}
}
}
}