mirror of
https://github.com/AlexMacocian/SystemExtensions.git
synced 2026-07-15 14:19:29 +00:00
Remove Slim dependency and adhere to Microsoft.Extensions standards
This commit is contained in:
@@ -1,59 +0,0 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using NSubstitute;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Http;
|
||||
|
||||
[TestClass]
|
||||
public class HttpClientResolverTests
|
||||
{
|
||||
private readonly HttpClientResolver httpClientResolver = new();
|
||||
private readonly Slim.IServiceProvider serviceProviderMock = Substitute.For<Slim.IServiceProvider>();
|
||||
|
||||
[TestMethod]
|
||||
public void CanResolve_IHttpClient_ReturnsTrue()
|
||||
{
|
||||
var type = typeof(IHttpClient<>);
|
||||
|
||||
var canResolve = this.httpClientResolver.CanResolve(type);
|
||||
|
||||
canResolve.Should().BeTrue();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanResolve_AnythingElse_ReturnsFalse()
|
||||
{
|
||||
var types = new Type[] { typeof(HttpClient), typeof(object), typeof(string), typeof(HttpClientResolverTests), typeof(int) };
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
var canResolve = this.httpClientResolver.CanResolve(type);
|
||||
|
||||
canResolve.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Resolve_NonGenericType_Throws()
|
||||
{
|
||||
Action action = new(() =>
|
||||
{
|
||||
this.httpClientResolver.Resolve(this.serviceProviderMock, typeof(IHttpClient<>));
|
||||
});
|
||||
|
||||
action.Should().Throw<Exception>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Resolve_RandomType_Throws()
|
||||
{
|
||||
Action action = new(() =>
|
||||
{
|
||||
this.httpClientResolver.Resolve(this.serviceProviderMock, typeof(string));
|
||||
});
|
||||
|
||||
action.Should().Throw<Exception>();
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NSubstitute;
|
||||
|
||||
namespace SystemExtensions.NetStandard.DependencyInjection.Tests.WebSockets;
|
||||
|
||||
[TestClass]
|
||||
public sealed class ClientWebSocketResolverTests
|
||||
{
|
||||
private readonly ClientWebSocketResolver webSocketResolver = new();
|
||||
private readonly Slim.IServiceProvider serviceProviderMock = Substitute.For<Slim.IServiceProvider>();
|
||||
|
||||
[TestMethod]
|
||||
public void CanResolve_IHttpClient_ReturnsTrue()
|
||||
{
|
||||
var type = typeof(IClientWebSocket<>);
|
||||
|
||||
var canResolve = this.webSocketResolver.CanResolve(type);
|
||||
|
||||
canResolve.Should().BeTrue();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanResolve_AnythingElse_ReturnsFalse()
|
||||
{
|
||||
var types = new Type[] { typeof(ClientWebSocket), typeof(object), typeof(string), typeof(ClientWebSocketResolverTests), typeof(int) };
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
var canResolve = this.webSocketResolver.CanResolve(type);
|
||||
|
||||
canResolve.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Resolve_TypedClient_ReturnsIClientWebSocketResolver()
|
||||
{
|
||||
var loggerMock = Substitute.For<ILogger<string>>();
|
||||
this.serviceProviderMock.GetService(typeof(ILogger<string>)).Returns(loggerMock);
|
||||
|
||||
var client = this.webSocketResolver.Resolve(this.serviceProviderMock, typeof(IClientWebSocket<string>));
|
||||
|
||||
client.Should().BeAssignableTo<IClientWebSocket<string>>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Resolve_NonGenericType_Throws()
|
||||
{
|
||||
Action action = new(() =>
|
||||
{
|
||||
this.webSocketResolver.Resolve(this.serviceProviderMock, typeof(IClientWebSocket<>));
|
||||
});
|
||||
|
||||
action.Should().Throw<Exception>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Resolve_RandomType_Throws()
|
||||
{
|
||||
Action action = new(() =>
|
||||
{
|
||||
this.webSocketResolver.Resolve(this.serviceProviderMock, typeof(string));
|
||||
});
|
||||
|
||||
action.Should().Throw<Exception>();
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
<RootNamespace>System</RootNamespace>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<Version>1.7</Version>
|
||||
<Version>1.8</Version>
|
||||
<Authors>Alexandru Macocian</Authors>
|
||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||
<Description>Extensions for the System namespace</Description>
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Net.Http;
|
||||
using System.Net.WebSockets;
|
||||
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Register a scoped <see cref="IHttpClient{TScope}"/> to be used by the DI engine.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the scoped <see cref="IHttpClient{TScope}"/>.</typeparam>
|
||||
/// <param name="services"><see cref="IServiceCollection"/>.</param>
|
||||
/// <returns><see cref="HttpClientBuilder{T}"/> to build the http client.</returns>
|
||||
public static HttpClientBuilder<T> RegisterHttpClient<T>(this IServiceCollection services)
|
||||
{
|
||||
services.ThrowIfNull(nameof(services));
|
||||
|
||||
return new HttpClientBuilder<T>(services);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a scoped <see cref="IClientWebSocket{TScope}"/> to be used by the DI engine.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the scoped <see cref="IClientWebSocket{TScope}"/>.</typeparam>
|
||||
/// <param name="services"><see cref="IServiceCollection"/>.</param>
|
||||
/// <returns><see cref="ClientWebSocketBuilder{T}"/> to build the websocket client.</returns>
|
||||
public static ClientWebSocketBuilder<T> RegisterClientWebSocket<T>(this IServiceCollection services)
|
||||
{
|
||||
services.ThrowIfNull(nameof(services));
|
||||
|
||||
return new ClientWebSocketBuilder<T>(services);
|
||||
}
|
||||
}
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Slim;
|
||||
using System.Net.Http;
|
||||
using System.Net.WebSockets;
|
||||
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class ServiceManagerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers a <see cref="ILoggerFactory"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceProducer"><see cref="IServiceProducer"/>.</param>
|
||||
/// <param name="loggerFactory">Factory that produces a <see cref="ILoggerFactory"/>.</param>
|
||||
/// <returns></returns>
|
||||
public static IServiceProducer RegisterLoggerFactory(this IServiceProducer serviceProducer, Func<Slim.IServiceProvider, ILoggerFactory> loggerFactory)
|
||||
{
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
serviceProducer.RegisterSingleton<ILoggerFactory, ILoggerFactory>(loggerFactory);
|
||||
return serviceProducer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a scoped <see cref="IHttpClient{TScope}"/> to be used by the DI engine.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the scoped <see cref="IHttpClient{TScope}"/>.</typeparam>
|
||||
/// <param name="services"><see cref="IServiceCollection"/>.</param>
|
||||
/// <returns><see cref="HttpClientBuilder{T}"/> to build the http client.</returns>
|
||||
public static HttpClientBuilder<T> RegisterHttpClient<T>(this IServiceCollection services)
|
||||
{
|
||||
services.ThrowIfNull(nameof(services));
|
||||
|
||||
return new HttpClientBuilder<T>(services);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a scoped <see cref="IClientWebSocket{TScope}"/> to be used by the DI engine.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the scoped <see cref="IClientWebSocket{TScope}"/>.</typeparam>
|
||||
/// <param name="services"><see cref="IServiceCollection"/>.</param>
|
||||
/// <returns><see cref="ClientWebSocketBuilder{T}"/> to build the websocket client.</returns>
|
||||
public static ClientWebSocketBuilder<T> RegisterClientWebSocket<T>(this IServiceCollection services)
|
||||
{
|
||||
services.ThrowIfNull(nameof(services));
|
||||
|
||||
return new ClientWebSocketBuilder<T>(services);
|
||||
}
|
||||
|
||||
[Obsolete($"{nameof(RegisterHttpFactory)} is obsolete. Please use {nameof(RegisterHttpClient)} for each service that requires an instance of {nameof(IHttpClient<object>)}.")]
|
||||
public static IServiceProducer RegisterHttpFactory(this IServiceProducer serviceProducer)
|
||||
{
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
serviceProducer.RegisterResolver(new HttpClientResolver());
|
||||
return serviceProducer;
|
||||
}
|
||||
[Obsolete($"{nameof(RegisterHttpFactory)} is obsolete. Please use {nameof(RegisterHttpClient)} for each service that requires an instance of {nameof(IHttpClient<object>)}.")]
|
||||
public static IServiceProducer RegisterHttpFactory(this IServiceProducer serviceProducer, Func<Slim.IServiceProvider, Type, HttpMessageHandler> handlerFactory)
|
||||
{
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
serviceProducer.RegisterResolver(
|
||||
new HttpClientResolver()
|
||||
.WithHttpMessageHandlerFactory(handlerFactory));
|
||||
return serviceProducer;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Slim;
|
||||
using System.Extensions;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
@@ -9,10 +8,10 @@ public sealed class HttpClientBuilder<T>
|
||||
{
|
||||
private readonly IServiceCollection services;
|
||||
|
||||
private Uri baseAddress;
|
||||
private Func<IServiceProvider, HttpMessageHandler> httpMessageHandlerFactory;
|
||||
private Uri? baseAddress;
|
||||
private Func<IServiceProvider, HttpMessageHandler>? httpMessageHandlerFactory;
|
||||
private Action<HttpRequestHeaders>? defaultRequestHeadersSetup;
|
||||
private bool disposeMessageHandler;
|
||||
private Action<HttpRequestHeaders> defaultRequestHeadersSetup;
|
||||
private long maxResponseBufferSize = 2147483647L; //2GB default HttpClient value [https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.maxresponsecontentbuffersize?view=net-6.0]
|
||||
private TimeSpan timeout = TimeSpan.FromSeconds(100); //100 seconds default HttpClient value [https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.timeout?view=net-6.0]
|
||||
|
||||
@@ -73,7 +72,11 @@ public sealed class HttpClientBuilder<T>
|
||||
new HttpClient<T>(this.httpMessageHandlerFactory(sp), this.disposeMessageHandler) :
|
||||
new HttpClient<T>(true);
|
||||
|
||||
client.BaseAddress = this.baseAddress;
|
||||
if (this.baseAddress is not null)
|
||||
{
|
||||
client.BaseAddress = this.baseAddress;
|
||||
}
|
||||
|
||||
this.defaultRequestHeadersSetup?.Invoke(client.DefaultRequestHeaders);
|
||||
client.MaxResponseContentBufferSize = this.maxResponseBufferSize;
|
||||
client.Timeout = this.timeout;
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
using Slim.Resolvers;
|
||||
using System.Linq;
|
||||
|
||||
namespace System.Net.Http;
|
||||
|
||||
[Obsolete($"Please use {nameof(Extensions.ServiceManagerExtensions.RegisterHttpClient)} for each use case of {nameof(IHttpClient<object>)}")]
|
||||
public sealed class HttpClientResolver : IDependencyResolver
|
||||
{
|
||||
private static readonly Type clientType = typeof(HttpClient<>);
|
||||
|
||||
/// <summary>
|
||||
/// Factory method. <see cref="Type"/> parameter of the factory is the scope of <see cref="IHttpClient{TScope}"/>.
|
||||
/// </summary>
|
||||
public Func<Slim.IServiceProvider, Type, HttpMessageHandler> HttpMessageHandlerFactory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="HttpMessageHandlerFactory"/>.
|
||||
/// </summary>
|
||||
/// <param name="factory">Factory method. <see cref="Type"/> parameter of the factory is the scope of <see cref="IHttpClient{TScope}"/>.</param>
|
||||
/// <returns></returns>
|
||||
public HttpClientResolver WithHttpMessageHandlerFactory(Func<Slim.IServiceProvider, Type, HttpMessageHandler> factory)
|
||||
{
|
||||
this.HttpMessageHandlerFactory = factory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public bool CanResolve(Type type)
|
||||
{
|
||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IHttpClient<>))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
|
||||
{
|
||||
var typedClientType = clientType.MakeGenericType(type.GetGenericArguments());
|
||||
var handler = this.HttpMessageHandlerFactory?.Invoke(serviceProvider, type.GetGenericArguments().First());
|
||||
var httpClient = handler is null ?
|
||||
Activator.CreateInstance(typedClientType) :
|
||||
Activator.CreateInstance(typedClientType, new object[] { handler });
|
||||
return httpClient;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace System.Logging;
|
||||
|
||||
public sealed record Log
|
||||
{
|
||||
public Exception Exception { get; set; }
|
||||
public DateTime LogTime { get; set; }
|
||||
public string Category { get; set; }
|
||||
public string EventId { get; set; }
|
||||
public LogLevel LogLevel { get; set; }
|
||||
public string Message { get; set; }
|
||||
public string CorrelationVector { get; set; }
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
using System.Net.Http;
|
||||
|
||||
namespace System.DependencyInjection.Models;
|
||||
|
||||
internal sealed class TypedHttpClientFactory<T>
|
||||
{
|
||||
public Func<Slim.IServiceProvider, HttpMessageHandler> Factory { get; set; }
|
||||
}
|
||||
+3
-4
@@ -6,7 +6,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Version>1.7.1</Version>
|
||||
<Version>1.8</Version>
|
||||
<Authors>Alexandru Macocian</Authors>
|
||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||
<Description>Extensions for the Slim Dependency Injection engine</Description>
|
||||
@@ -22,9 +22,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CorrelationVector" Version="1.0.42" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
|
||||
<PackageReference Include="Slim" Version="1.9.2" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.6.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.1" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.8.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Slim.Resolvers;
|
||||
|
||||
namespace System.Net.WebSockets;
|
||||
|
||||
[Obsolete($"Please use {nameof(Extensions.ServiceManagerExtensions.RegisterClientWebSocket)} for each use case of {nameof(IClientWebSocket<object>)}")]
|
||||
public sealed class ClientWebSocketResolver : IDependencyResolver
|
||||
{
|
||||
private static readonly Type ClientType = typeof(ClientWebSocket<>);
|
||||
private static readonly Type LoggerType = typeof(ILogger<>);
|
||||
|
||||
public bool CanResolve(Type type)
|
||||
{
|
||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IClientWebSocket<>))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
|
||||
{
|
||||
var typedClientType = ClientType.MakeGenericType(type.GetGenericArguments());
|
||||
var typedLoggerType = LoggerType.MakeGenericType(type.GetGenericArguments());
|
||||
var logger = serviceProvider.GetService(typedLoggerType);
|
||||
var client = Activator.CreateInstance(typedClientType, new object[] { logger });
|
||||
return client;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user