mirror of
https://github.com/AlexMacocian/SystemExtensions.git
synced 2026-07-15 14:19:29 +00:00
IClientWebSocket builder
This commit is contained in:
@@ -35,14 +35,6 @@ public class HttpClientResolverTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void Resolve_TypedClient_ReturnsIHttpClient()
|
|
||||||
{
|
|
||||||
var client = this.httpClientResolver.Resolve(this.serviceProviderMock, typeof(IHttpClient<string>));
|
|
||||||
|
|
||||||
client.Should().BeAssignableTo<IHttpClient<string>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Resolve_NonGenericType_Throws()
|
public void Resolve_NonGenericType_Throws()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using global::SystemExtensions.NetStandard.DependencyInjection.Tests.Http.Models;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using NSubstitute;
|
||||||
|
using System;
|
||||||
|
using System.Extensions;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SystemExtensions.NetStandard.DependencyInjection.Tests.WebSockets;
|
||||||
|
[TestClass]
|
||||||
|
public sealed class HttpClientBuilderTests
|
||||||
|
{
|
||||||
|
private readonly ClientWebSocketBuilder<object> clientWebSocketBuilder;
|
||||||
|
private readonly IServiceCollection serviceProducerMock = Substitute.For<IServiceCollection>();
|
||||||
|
|
||||||
|
public HttpClientBuilderTests()
|
||||||
|
{
|
||||||
|
this.clientWebSocketBuilder = new ClientWebSocketBuilder<object>(this.serviceProducerMock);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Constructor_NullServiceProducer_Throws()
|
||||||
|
{
|
||||||
|
var action = () => new ClientWebSocketBuilder<object>(null);
|
||||||
|
|
||||||
|
action.Should().Throw<ArgumentNullException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void WithInnerWebSocket_NullHandler_Throws()
|
||||||
|
{
|
||||||
|
var action = () => this.clientWebSocketBuilder.WithInnerWebSocket(null);
|
||||||
|
|
||||||
|
action.Should().Throw<ArgumentNullException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void WIthInnerWebSocketFactory_NullBaseAddress_Throws()
|
||||||
|
{
|
||||||
|
var action = () => this.clientWebSocketBuilder.WithInnerWebSocketFactory(null);
|
||||||
|
|
||||||
|
action.Should().Throw<ArgumentNullException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void Build_ReturnsServiceProducer()
|
||||||
|
{
|
||||||
|
var producer = this.clientWebSocketBuilder.Build();
|
||||||
|
|
||||||
|
producer.Should().BeEquivalentTo(this.serviceProducerMock);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task ClientWebSocketBuilder_RegistersClientCorrectly_IServiceProviderReturnsExpected()
|
||||||
|
{
|
||||||
|
var container = new ServiceCollection();
|
||||||
|
var innerWebSocket = new ClientWebSocket();
|
||||||
|
container.RegisterClientWebSocket<object>()
|
||||||
|
.WithInnerWebSocket(innerWebSocket)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var di = container.BuildServiceProvider();
|
||||||
|
var client = di.GetService<IClientWebSocket<object>>();
|
||||||
|
client.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -2,6 +2,7 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Slim;
|
using Slim;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
|
||||||
namespace System.Extensions;
|
namespace System.Extensions;
|
||||||
|
|
||||||
@@ -34,6 +35,19 @@ public static class ServiceManagerExtensions
|
|||||||
return new HttpClientBuilder<T>(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>)}.")]
|
[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)
|
public static IServiceProducer RegisterHttpFactory(this IServiceProducer serviceProducer)
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-1
@@ -6,10 +6,11 @@
|
|||||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Version>1.7</Version>
|
<Version>1.7.1</Version>
|
||||||
<Authors>Alexandru Macocian</Authors>
|
<Authors>Alexandru Macocian</Authors>
|
||||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||||
<Description>Extensions for the Slim Dependency Injection engine</Description>
|
<Description>Extensions for the Slim Dependency Injection engine</Description>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Extensions;
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
|
||||||
|
namespace System.Net.Http;
|
||||||
|
|
||||||
|
public sealed class ClientWebSocketBuilder<T>
|
||||||
|
{
|
||||||
|
private readonly IServiceCollection services;
|
||||||
|
|
||||||
|
private ClientWebSocket? innerWebSocket;
|
||||||
|
private Func<IServiceProvider, ClientWebSocket>? innerWebSocketFactory;
|
||||||
|
|
||||||
|
internal ClientWebSocketBuilder(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.ThrowIfNull(nameof(services));
|
||||||
|
this.services = services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientWebSocketBuilder<T> WithInnerWebSocket(ClientWebSocket innerWebSocket)
|
||||||
|
{
|
||||||
|
this.innerWebSocket = innerWebSocket.ThrowIfNull(nameof(innerWebSocket));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientWebSocketBuilder<T> WithInnerWebSocketFactory(Func<IServiceProvider, ClientWebSocket> innerWebSocketFactory)
|
||||||
|
{
|
||||||
|
this.innerWebSocketFactory = innerWebSocketFactory.ThrowIfNull(nameof(innerWebSocketFactory));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IServiceCollection Build()
|
||||||
|
{
|
||||||
|
this.services.AddScoped<IClientWebSocket<T>>(sp =>
|
||||||
|
{
|
||||||
|
var logger = sp.GetService<ILogger<T>>();
|
||||||
|
if (logger is null)
|
||||||
|
{
|
||||||
|
return new ClientWebSocket<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.innerWebSocketFactory is not null)
|
||||||
|
{
|
||||||
|
return new ClientWebSocket<T>(this.innerWebSocketFactory(sp), logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.innerWebSocket is not null)
|
||||||
|
{
|
||||||
|
return new ClientWebSocket<T>(this.innerWebSocket, logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ClientWebSocket<T>(logger);
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.services;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
using Slim.Resolvers;
|
using Slim.Resolvers;
|
||||||
|
|
||||||
namespace System.Net.WebSockets;
|
namespace System.Net.WebSockets;
|
||||||
|
|
||||||
|
[Obsolete($"Please use {nameof(Extensions.ServiceManagerExtensions.RegisterClientWebSocket)} for each use case of {nameof(IClientWebSocket<object>)}")]
|
||||||
public sealed class ClientWebSocketResolver : IDependencyResolver
|
public sealed class ClientWebSocketResolver : IDependencyResolver
|
||||||
{
|
{
|
||||||
private static readonly Type ClientType = typeof(ClientWebSocket<>);
|
private static readonly Type ClientType = typeof(ClientWebSocket<>);
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ public sealed class SecureString
|
|||||||
private byte[] encryptedValue;
|
private byte[] encryptedValue;
|
||||||
|
|
||||||
public string Value {
|
public string Value {
|
||||||
get => this.encryptedValue is not null ? Encoding.UTF8.GetString(ProtectedData.Unprotect(this.encryptedValue, optionalEntropy, DataProtectionScope.CurrentUser)) : null;
|
get => this.encryptedValue is not null ? Encoding.UTF8.GetString(ProtectedData.Unprotect(this.encryptedValue, optionalEntropy, DataProtectionScope.CurrentUser)) : string.Empty;
|
||||||
private set => this.encryptedValue = ProtectedData.Protect(Encoding.UTF8.GetBytes(value), optionalEntropy, DataProtectionScope.CurrentUser);
|
private set => this.encryptedValue = value is not null
|
||||||
|
? ProtectedData.Protect(Encoding.UTF8.GetBytes(value), optionalEntropy, DataProtectionScope.CurrentUser)
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecureString(string value)
|
public SecureString(string value)
|
||||||
@@ -42,7 +44,7 @@ public sealed class SecureString
|
|||||||
return this.Value;
|
return this.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly SecureString Empty = new(string.Empty);
|
public static readonly SecureString Empty = new(null);
|
||||||
public static implicit operator string(SecureString ss) => ss is null ? string.Empty : ss.Value;
|
public static implicit operator string(SecureString ss) => ss is null ? string.Empty : ss.Value;
|
||||||
public static implicit operator SecureString(string s) => new(s);
|
public static implicit operator SecureString(string s) => new(s);
|
||||||
public static SecureString operator +(SecureString ss1, SecureString ss2)
|
public static SecureString operator +(SecureString ss1, SecureString ss2)
|
||||||
@@ -79,6 +81,11 @@ public sealed class SecureString
|
|||||||
}
|
}
|
||||||
public static bool operator ==(SecureString ss1, SecureString ss2)
|
public static bool operator ==(SecureString ss1, SecureString ss2)
|
||||||
{
|
{
|
||||||
|
if (ss1 is null && ss2 is null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return ss1?.Value == ss2?.Value;
|
return ss1?.Value == ss2?.Value;
|
||||||
}
|
}
|
||||||
public static bool operator !=(SecureString ss1, SecureString ss2)
|
public static bool operator !=(SecureString ss1, SecureString ss2)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||||
<RootNamespace>System</RootNamespace>
|
<RootNamespace>System</RootNamespace>
|
||||||
<Version>1.3.0</Version>
|
<Version>1.3.1</Version>
|
||||||
<Authors>Alexandru Macocian</Authors>
|
<Authors>Alexandru Macocian</Authors>
|
||||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||||
<Description>Security extensions for the System namespace</Description>
|
<Description>Security extensions for the System namespace</Description>
|
||||||
|
|||||||
Reference in New Issue
Block a user