// ------------------------------------------------------------------------
// 版权信息
// 版权归百小僧及百签科技(广东)有限公司所有。
// 所有权利保留。
// 官方网站:https://baiqian.com
//
// 许可证信息
// 项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// ------------------------------------------------------------------------
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using System.Reflection;
using System.Text;
using ThingsGateway.Extension;
namespace ThingsGateway.HttpRemote;
///
/// HTTP 远程请求构建器
///
public sealed class HttpRemoteBuilder
{
///
/// 集合
///
internal IList>>? _httpContentConverterProviders;
///
/// 集合
///
internal IList>>? _httpContentProcessorProviders;
///
/// 集合
///
internal IList>>? _httpDeclarativeExtractors;
///
/// 类型集合
///
internal HashSet? _httpDeclarativeTypes;
///
/// 实现类型
///
internal Type? _objectContentConverterFactoryType;
///
/// 添加 请求内容处理器
///
/// 支持多次调用。
/// 实例提供器
///
///
///
public HttpRemoteBuilder AddHttpContentProcessors(Func> configure)
{
// 空检查
ArgumentNullException.ThrowIfNull(configure);
_httpContentProcessorProviders ??= new List>>();
_httpContentProcessorProviders.Add(configure);
return this;
}
///
/// 添加 响应内容转换器
///
/// 支持多次调用。
/// 实例提供器
///
///
///
public HttpRemoteBuilder AddHttpContentConverters(Func> configure)
{
// 空检查
ArgumentNullException.ThrowIfNull(configure);
_httpContentConverterProviders ??= new List>>();
_httpContentConverterProviders.Add(configure);
return this;
}
///
/// 设置 对象内容转换器工厂
///
///
///
///
///
///
///
public HttpRemoteBuilder UseObjectContentConverterFactory()
where TFactory : IObjectContentConverterFactory =>
UseObjectContentConverterFactory(typeof(TFactory));
///
/// 设置 对象内容转换器工厂
///
///
///
///
///
///
///
///
public HttpRemoteBuilder UseObjectContentConverterFactory(Type factoryType)
{
// 空检查
ArgumentNullException.ThrowIfNull(factoryType);
// 检查类型是否实现了 IObjectContentConverterFactory 接口
if (!typeof(IObjectContentConverterFactory).IsAssignableFrom(factoryType))
{
throw new ArgumentException(
$"`{factoryType}` type is not assignable from `{typeof(IObjectContentConverterFactory)}`.",
nameof(factoryType));
}
_objectContentConverterFactoryType = factoryType;
return this;
}
///
/// 添加 HTTP 声明式服务
///
///
///
///
///
///
///
public HttpRemoteBuilder AddHttpDeclarative()
where TDeclarative : IHttpDeclarative =>
AddHttpDeclarative(typeof(TDeclarative));
///
/// 添加 HTTP 声明式服务
///
///
///
///
///
///
///
///
public HttpRemoteBuilder AddHttpDeclarative(Type declarativeType)
{
// 空检查
ArgumentNullException.ThrowIfNull(declarativeType);
// 检查类型是否是接口且实现了 IHttpDeclarative 接口
if (!declarativeType.IsInterface || !typeof(IHttpDeclarative).IsAssignableFrom(declarativeType))
{
throw new ArgumentException(
$"`{declarativeType}` type is not assignable from `{typeof(IHttpDeclarative)}` or interface.",
nameof(declarativeType));
}
_httpDeclarativeTypes ??= [];
_httpDeclarativeTypes.Add(declarativeType);
return this;
}
///
/// 添加 HTTP 声明式服务
///
///
/// 集合
///
///
///
///
///
public HttpRemoteBuilder AddHttpDeclaratives(params IEnumerable declarativeTypes)
{
// 空检查
ArgumentNullException.ThrowIfNull(declarativeTypes);
foreach (var declarativeType in declarativeTypes)
{
AddHttpDeclarative(declarativeType);
}
return this;
}
///
/// 扫描程序集并添加 HTTP 声明式服务
///
/// 集合
///
///
///
public HttpRemoteBuilder AddHttpDeclarativeFromAssemblies(params IEnumerable assemblies)
{
// 空检查
ArgumentNullException.ThrowIfNull(assemblies);
AddHttpDeclaratives(assemblies.SelectMany(ass =>
(ass?.GetExportedTypes() ?? Enumerable.Empty()).Where(t =>
t.IsInterface && typeof(IHttpDeclarative).IsAssignableFrom(t))));
return this;
}
///
/// 添加 HTTP 声明式 提取器
///
/// 支持多次调用。
/// 实例提供器
///
///
///
public HttpRemoteBuilder AddHttpDeclarativeExtractors(Func> configure)
{
// 空检查
ArgumentNullException.ThrowIfNull(configure);
_httpDeclarativeExtractors ??= new List>>();
_httpDeclarativeExtractors.Add(configure);
return this;
}
///
/// 扫描程序集并添加 HTTP 声明式 提取器
///
/// 支持多次调用。
/// 集合
///
///
///
public HttpRemoteBuilder AddHttpDeclarativeExtractorFromAssemblies(params IEnumerable assemblies)
{
// 空检查
ArgumentNullException.ThrowIfNull(assemblies);
return AddHttpDeclarativeExtractors(() => assemblies.SelectMany(ass =>
(ass?.GetExportedTypes() ?? Enumerable.Empty()).Where(t =>
t.HasDefinePublicParameterlessConstructor() && typeof(IHttpDeclarativeExtractor).IsAssignableFrom(t))
.Select(t => (IHttpDeclarativeExtractor)Activator.CreateInstance(t)!)));
}
///
/// 构建模块服务
///
///
///
///
internal void Build(IServiceCollection services)
{
// 注册 CodePagesEncodingProvider,使得程序能够识别并使用 Windows 代码页中的各种编码
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
// 注册日志服务
services.AddLogging();
// 注册默认 HttpClient 客户端
if (services.All(u => u.ServiceType != typeof(IHttpClientFactory)))
{
services.AddHttpClient();
}
// 检查是否配置(注册)了日志程序
var isLoggingRegistered = services.Any(u => u.ServiceType == typeof(ILoggerProvider));
// 注册并配置 HttpRemoteOptions 选项服务
services.Configure(options =>
{
options.HttpDeclarativeExtractors = _httpDeclarativeExtractors?.AsReadOnly();
options.IsLoggingRegistered = isLoggingRegistered;
});
// 注册 HttpContent 内容处理器工厂
services.TryAddSingleton(provider =>
new HttpContentProcessorFactory(provider,
_httpContentProcessorProviders?.SelectMany(u => u.Invoke()).ToArray()));
// 注册 HttpContent 内容转换器工厂
services.TryAddSingleton(provider =>
new HttpContentConverterFactory(provider,
_httpContentConverterProviders?.SelectMany(u => u.Invoke()).ToArray()));
// 注册对象内容转换器工厂
services.TryAddSingleton();
// 注册 HTTP 远程请求服务
services.TryAddSingleton();
// 检查是否自定义了对象内容转换器工厂,如果存在则替换
if (_objectContentConverterFactoryType is not null &&
_objectContentConverterFactoryType != typeof(ObjectContentConverterFactory))
{
services.Replace(ServiceDescriptor.Singleton(typeof(IObjectContentConverterFactory),
_objectContentConverterFactoryType));
}
// 构建 HTTP 声明式远程请求服务
BuildHttpDeclarativeServices(services);
}
///
/// 构建 HTTP 声明式远程请求服务
///
///
///
///
internal void BuildHttpDeclarativeServices(IServiceCollection services)
{
// 空检查
if (_httpDeclarativeTypes is null)
{
return;
}
// 初始化 HTTP 声明式远程请求代理类类型
var httpDeclarativeDispatchProxyType = typeof(HttpDeclarativeDispatchProxy);
// 遍历 HTTP 声明式远程请求类型并注册为服务
foreach (var httpDeclarativeType in _httpDeclarativeTypes)
{
services.TryAddSingleton(httpDeclarativeType, provider =>
{
// 创建 HTTP 声明式远程请求代理实例
var httpDeclarative =
DispatchProxyAsync.Create(httpDeclarativeType, httpDeclarativeDispatchProxyType) as
HttpDeclarativeDispatchProxy;
// 空检查
ArgumentNullException.ThrowIfNull(httpDeclarative);
// 解析 IHttpRemoteService 服务并设置给 RemoteService 属性
httpDeclarative.RemoteService = provider.GetRequiredService();
return httpDeclarative;
});
}
}
}