From 124ae942b5719def6b7b313522ef960bef0d553f Mon Sep 17 00:00:00 2001 From: Alex Macocian Date: Sun, 11 Jan 2026 01:02:42 +0100 Subject: [PATCH] Remove Slim dependency and adhere to Microsoft.Extensions standards --- .../Http/HttpClientResolverTests.cs | 59 --------------- .../ClientWebSocketResolverTests.cs | 71 ------------------- .../SystemExtensions.NetCore.csproj | 2 +- .../Extensions/ServiceCollectionExtensions.cs | 34 +++++++++ .../Extensions/ServiceManagerExtensions.cs | 69 ------------------ .../Http/HttpClientBuilder.cs | 13 ++-- .../Http/HttpClientResolver.cs | 46 ------------ .../Models/Log.cs | 14 ---- .../Models/TypedHttpClientFactory.cs | 8 --- ...ons.NetStandard.DependencyInjection.csproj | 7 +- .../WebSockets/ClientWebSocketResolver.cs | 30 -------- 11 files changed, 46 insertions(+), 307 deletions(-) delete mode 100644 SystemExtensions.DependencyInjection.Tests/Http/HttpClientResolverTests.cs delete mode 100644 SystemExtensions.DependencyInjection.Tests/WebSockets/ClientWebSocketResolverTests.cs create mode 100644 SystemExtensions.NetStandard.DependencyInjection/Extensions/ServiceCollectionExtensions.cs delete mode 100644 SystemExtensions.NetStandard.DependencyInjection/Extensions/ServiceManagerExtensions.cs delete mode 100644 SystemExtensions.NetStandard.DependencyInjection/Http/HttpClientResolver.cs delete mode 100644 SystemExtensions.NetStandard.DependencyInjection/Models/Log.cs delete mode 100644 SystemExtensions.NetStandard.DependencyInjection/Models/TypedHttpClientFactory.cs delete mode 100644 SystemExtensions.NetStandard.DependencyInjection/WebSockets/ClientWebSocketResolver.cs diff --git a/SystemExtensions.DependencyInjection.Tests/Http/HttpClientResolverTests.cs b/SystemExtensions.DependencyInjection.Tests/Http/HttpClientResolverTests.cs deleted file mode 100644 index 679452d..0000000 --- a/SystemExtensions.DependencyInjection.Tests/Http/HttpClientResolverTests.cs +++ /dev/null @@ -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(); - - [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(); - } - - [TestMethod] - public void Resolve_RandomType_Throws() - { - Action action = new(() => - { - this.httpClientResolver.Resolve(this.serviceProviderMock, typeof(string)); - }); - - action.Should().Throw(); - } -} diff --git a/SystemExtensions.DependencyInjection.Tests/WebSockets/ClientWebSocketResolverTests.cs b/SystemExtensions.DependencyInjection.Tests/WebSockets/ClientWebSocketResolverTests.cs deleted file mode 100644 index c10d298..0000000 --- a/SystemExtensions.DependencyInjection.Tests/WebSockets/ClientWebSocketResolverTests.cs +++ /dev/null @@ -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(); - - [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>(); - this.serviceProviderMock.GetService(typeof(ILogger)).Returns(loggerMock); - - var client = this.webSocketResolver.Resolve(this.serviceProviderMock, typeof(IClientWebSocket)); - - client.Should().BeAssignableTo>(); - } - - [TestMethod] - public void Resolve_NonGenericType_Throws() - { - Action action = new(() => - { - this.webSocketResolver.Resolve(this.serviceProviderMock, typeof(IClientWebSocket<>)); - }); - - action.Should().Throw(); - } - - [TestMethod] - public void Resolve_RandomType_Throws() - { - Action action = new(() => - { - this.webSocketResolver.Resolve(this.serviceProviderMock, typeof(string)); - }); - - action.Should().Throw(); - } -} diff --git a/SystemExtensions.NetCore/SystemExtensions.NetCore.csproj b/SystemExtensions.NetCore/SystemExtensions.NetCore.csproj index 944700a..70a3f87 100644 --- a/SystemExtensions.NetCore/SystemExtensions.NetCore.csproj +++ b/SystemExtensions.NetCore/SystemExtensions.NetCore.csproj @@ -8,7 +8,7 @@ System LICENSE true - 1.7 + 1.8 Alexandru Macocian https://github.com/AlexMacocian/SystemExtensions Extensions for the System namespace diff --git a/SystemExtensions.NetStandard.DependencyInjection/Extensions/ServiceCollectionExtensions.cs b/SystemExtensions.NetStandard.DependencyInjection/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..be2c422 --- /dev/null +++ b/SystemExtensions.NetStandard.DependencyInjection/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,34 @@ +using Microsoft.Extensions.DependencyInjection; +using System.Net.Http; +using System.Net.WebSockets; + +namespace System.Extensions; + +public static class ServiceCollectionExtensions +{ + /// + /// Register a scoped to be used by the DI engine. + /// + /// Type of the scoped . + /// . + /// to build the http client. + public static HttpClientBuilder RegisterHttpClient(this IServiceCollection services) + { + services.ThrowIfNull(nameof(services)); + + return new HttpClientBuilder(services); + } + + /// + /// Register a scoped to be used by the DI engine. + /// + /// Type of the scoped . + /// . + /// to build the websocket client. + public static ClientWebSocketBuilder RegisterClientWebSocket(this IServiceCollection services) + { + services.ThrowIfNull(nameof(services)); + + return new ClientWebSocketBuilder(services); + } +} diff --git a/SystemExtensions.NetStandard.DependencyInjection/Extensions/ServiceManagerExtensions.cs b/SystemExtensions.NetStandard.DependencyInjection/Extensions/ServiceManagerExtensions.cs deleted file mode 100644 index cc9d9c7..0000000 --- a/SystemExtensions.NetStandard.DependencyInjection/Extensions/ServiceManagerExtensions.cs +++ /dev/null @@ -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 -{ - /// - /// Registers a . - /// - /// . - /// Factory that produces a . - /// - public static IServiceProducer RegisterLoggerFactory(this IServiceProducer serviceProducer, Func loggerFactory) - { - serviceProducer.ThrowIfNull(nameof(serviceProducer)); - - serviceProducer.RegisterSingleton(loggerFactory); - return serviceProducer; - } - - /// - /// Register a scoped to be used by the DI engine. - /// - /// Type of the scoped . - /// . - /// to build the http client. - public static HttpClientBuilder RegisterHttpClient(this IServiceCollection services) - { - services.ThrowIfNull(nameof(services)); - - return new HttpClientBuilder(services); - } - - /// - /// Register a scoped to be used by the DI engine. - /// - /// Type of the scoped . - /// . - /// to build the websocket client. - public static ClientWebSocketBuilder RegisterClientWebSocket(this IServiceCollection services) - { - services.ThrowIfNull(nameof(services)); - - return new ClientWebSocketBuilder(services); - } - - [Obsolete($"{nameof(RegisterHttpFactory)} is obsolete. Please use {nameof(RegisterHttpClient)} for each service that requires an instance of {nameof(IHttpClient)}.")] - 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)}.")] - public static IServiceProducer RegisterHttpFactory(this IServiceProducer serviceProducer, Func handlerFactory) - { - serviceProducer.ThrowIfNull(nameof(serviceProducer)); - - serviceProducer.RegisterResolver( - new HttpClientResolver() - .WithHttpMessageHandlerFactory(handlerFactory)); - return serviceProducer; - } -} diff --git a/SystemExtensions.NetStandard.DependencyInjection/Http/HttpClientBuilder.cs b/SystemExtensions.NetStandard.DependencyInjection/Http/HttpClientBuilder.cs index 763a768..3d4f104 100644 --- a/SystemExtensions.NetStandard.DependencyInjection/Http/HttpClientBuilder.cs +++ b/SystemExtensions.NetStandard.DependencyInjection/Http/HttpClientBuilder.cs @@ -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 { private readonly IServiceCollection services; - private Uri baseAddress; - private Func httpMessageHandlerFactory; + private Uri? baseAddress; + private Func? httpMessageHandlerFactory; + private Action? defaultRequestHeadersSetup; private bool disposeMessageHandler; - private Action 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 new HttpClient(this.httpMessageHandlerFactory(sp), this.disposeMessageHandler) : new HttpClient(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; diff --git a/SystemExtensions.NetStandard.DependencyInjection/Http/HttpClientResolver.cs b/SystemExtensions.NetStandard.DependencyInjection/Http/HttpClientResolver.cs deleted file mode 100644 index 0f9cf6d..0000000 --- a/SystemExtensions.NetStandard.DependencyInjection/Http/HttpClientResolver.cs +++ /dev/null @@ -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)}")] -public sealed class HttpClientResolver : IDependencyResolver -{ - private static readonly Type clientType = typeof(HttpClient<>); - - /// - /// Factory method. parameter of the factory is the scope of . - /// - public Func HttpMessageHandlerFactory { get; set; } - - /// - /// Sets the . - /// - /// Factory method. parameter of the factory is the scope of . - /// - public HttpClientResolver WithHttpMessageHandlerFactory(Func 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; - } -} \ No newline at end of file diff --git a/SystemExtensions.NetStandard.DependencyInjection/Models/Log.cs b/SystemExtensions.NetStandard.DependencyInjection/Models/Log.cs deleted file mode 100644 index 65faa1e..0000000 --- a/SystemExtensions.NetStandard.DependencyInjection/Models/Log.cs +++ /dev/null @@ -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; } -} \ No newline at end of file diff --git a/SystemExtensions.NetStandard.DependencyInjection/Models/TypedHttpClientFactory.cs b/SystemExtensions.NetStandard.DependencyInjection/Models/TypedHttpClientFactory.cs deleted file mode 100644 index 428dc97..0000000 --- a/SystemExtensions.NetStandard.DependencyInjection/Models/TypedHttpClientFactory.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Net.Http; - -namespace System.DependencyInjection.Models; - -internal sealed class TypedHttpClientFactory -{ - public Func Factory { get; set; } -} diff --git a/SystemExtensions.NetStandard.DependencyInjection/SystemExtensions.NetStandard.DependencyInjection.csproj b/SystemExtensions.NetStandard.DependencyInjection/SystemExtensions.NetStandard.DependencyInjection.csproj index 4d629ea..d097b1b 100644 --- a/SystemExtensions.NetStandard.DependencyInjection/SystemExtensions.NetStandard.DependencyInjection.csproj +++ b/SystemExtensions.NetStandard.DependencyInjection/SystemExtensions.NetStandard.DependencyInjection.csproj @@ -6,7 +6,7 @@ LICENSE true latest - 1.7.1 + 1.8 Alexandru Macocian https://github.com/AlexMacocian/SystemExtensions Extensions for the Slim Dependency Injection engine @@ -22,9 +22,8 @@ - - - + + diff --git a/SystemExtensions.NetStandard.DependencyInjection/WebSockets/ClientWebSocketResolver.cs b/SystemExtensions.NetStandard.DependencyInjection/WebSockets/ClientWebSocketResolver.cs deleted file mode 100644 index ee9c4da..0000000 --- a/SystemExtensions.NetStandard.DependencyInjection/WebSockets/ClientWebSocketResolver.cs +++ /dev/null @@ -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)}")] -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; - } -}