Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
build_version_base:
description: 'Build version number X.Y.Z'
required: false
default: 0.9.0
default: 0.10.0

jobs:

Expand Down Expand Up @@ -37,7 +37,7 @@ jobs:
- name: Install .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
dotnet-version: 9.0.x

# Create the NuGet packages in the folder from the environment variable NuGetDirectory
- name: Build NuGet packages
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
dotnet-version: '9.0.x'
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
Expand Down Expand Up @@ -81,7 +81,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
dotnet-version: '9.0.x'
- name: Install dependencies
run: dotnet restore CommonNet.Extensions.Tests/CommonNet.Extensions.Tests.csproj
- name: Build Tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageDescription>Various Dependency Injectionextensions.</PackageDescription>
<PackageDescription>Various Dependency Injection extensions.</PackageDescription>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ public static IServiceCollection AddSingleton<TService1, TService2, TImplementat
where TService2 : class
{
return services
//.AddSingleton<TService1>(sp => sp.GetRequiredService<TIm>)
.AddSingleton<TService1, TImplementation>(implementationFactory)
.AddSingleton(sp => (sp.GetRequiredService<TService1>() as TService2)!);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,47 @@ public void AddSingleton_ShouldSucceed()
bif2.Should().NotBe(bif1);
}

[Fact]
public void AddSingletonWithFactory_ShouldSucceed()
{
var services = new ServiceCollection();

services
.AddSingletonIf<IInheritedIface4, IInheritedIface3, IInheritedIface2, IBaseInterface1, A4_1>(true, sp => new A4_1())
.AddSingletonIf<IBaseInterface2, IBaseInterface3, IBaseInterface4, IBaseInterface5, B4_2>(true, sp => new B4_2());

using var sp = services.BuildServiceProvider();

var iif4 = sp.GetRequiredService<IInheritedIface4>();
iif4.Should().NotBeNull();
var iif3 = sp.GetRequiredService<IInheritedIface3>();
iif3.Should().NotBeNull();
var iif2 = sp.GetRequiredService<IInheritedIface2>();
iif2.Should().NotBeNull();
var bif1 = sp.GetRequiredService<IBaseInterface1>();
bif1.Should().NotBeNull();

iif4.Should().Be(iif3);
iif3.Should().Be(iif2);
iif2.Should().Be(bif1);


var bif2 = sp.GetRequiredService<IBaseInterface2>();
bif2.Should().NotBeNull();
var bif3 = sp.GetRequiredService<IBaseInterface3>();
bif3.Should().NotBeNull();
var bif4 = sp.GetRequiredService<IBaseInterface4>();
bif4.Should().NotBeNull();
var bif5 = sp.GetRequiredService<IBaseInterface5>();
bif5.Should().NotBeNull();

bif2.Should().Be(bif3);
bif3.Should().Be(bif4);
bif4.Should().Be(bif5);

bif2.Should().NotBe(bif1);
}

[Fact]
public void AddSingletonFact_ShouldSucceed()
{
Expand Down
8 changes: 4 additions & 4 deletions CommonNet.Extensions.Tests/CommonNet.Extensions.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net8.0;net7.0;net6.0;net48</TargetFrameworks>
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net8.0;net9.0;net48</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

Expand All @@ -24,8 +24,8 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" />
<PackageReference Include="FluentAssertions.Analyzers">
<PackageReference Include="AwesomeAssertions" />
<PackageReference Include="AwesomeAssertions.Analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,74 @@ public async Task AsTask_WithTimeout_ShouldCancel_WhenTimeoutIsReached()

task.IsCanceled.Should().BeTrue();
}


#if NET8_0_OR_GREATER

[Fact]
public async Task WaitAsync_WaitHandle_Signaled_CompletesTask()
{
using var manualEvent = new ManualResetEvent(false);
WaitHandle waitHandle = manualEvent;
var cancellationToken = CancellationToken.None;

var task = waitHandle.WaitAsync(cancellationToken);
manualEvent.Set();

await task.Awaiting(t => t).Should().NotThrowAsync();
}

[Fact]
public async Task WaitAsync_WaitHandle_Canceled_ThrowsTaskCanceledException()
{
using var manualEvent = new ManualResetEvent(false);
WaitHandle waitHandle = manualEvent;
var cts = new CancellationTokenSource();

var task = waitHandle.WaitAsync(cts.Token);
cts.Cancel();

await task.Awaiting(t => t).Should().ThrowAsync<TaskCanceledException>();
}

[Fact]
public async Task WaitAsync_ManualResetEventSlim_Signaled_CompletesTask()
{

using var manualResetEvent = new ManualResetEventSlim(false);
var cancellationToken = CancellationToken.None;

var task = manualResetEvent.WaitAsync(cancellationToken);
manualResetEvent.Set();

await task.Awaiting(t => t).Should().NotThrowAsync();
}

[Fact]
public async Task WaitAsync_ManualResetEventSlim_Canceled_ThrowsTaskCanceledException()
{
// Arrange
using var manualResetEvent = new ManualResetEventSlim(false);
var cts = new CancellationTokenSource();

var task = manualResetEvent.WaitAsync(cts.Token);
cts.Cancel();

await task.Awaiting(t => t).Should().ThrowAsync<TaskCanceledException>();
}

[Fact]
public void WaitAsync_WaitHandle_Null_ThrowsArgumentNullException()
{
WaitHandle waitHandle = null!;
var cancellationToken = CancellationToken.None;

var func = () => waitHandle.WaitAsync(cancellationToken);
func.Should().ThrowAsync<ArgumentException>();
}

#endif

}

#pragma warning restore xUnit1031
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using CommunityToolkit.Diagnostics;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace System.Collections.Generic;

Expand All @@ -25,14 +26,22 @@ Func<TKey, TValue> valueFactory
where TKey : notnull
{
Guard.IsNotNull(self);
Guard.IsNotNull(key);
Guard.IsNotNull(valueFactory);

#if NET8_0_OR_GREATER
ref var value = ref CollectionsMarshal.GetValueRefOrAddDefault(self, key, out var exists);
if (exists)
{
return value!;
}
value = valueFactory(key);
#else
if (!self.TryGetValue(key, out var value))
{
value = valueFactory(key);
self.Add(key, value);
}
#endif
return value;
}

Expand All @@ -51,13 +60,21 @@ TValue newValue
where TKey : notnull
{
Guard.IsNotNull(self);
Guard.IsNotNull(key);

#if NET8_0_OR_GREATER
ref var value = ref CollectionsMarshal.GetValueRefOrAddDefault(self, key, out var exists);
if (exists)
{
return value!;
}
value = newValue;
#else
if (!self.TryGetValue(key, out var value))
{
value = newValue;
self.Add(key, value);
}
#endif
return value;
}

Expand Down Expand Up @@ -100,21 +117,32 @@ Func<TKey, TValue, TValue> updateValueFactory
where TKey : notnull
{
Guard.IsNotNull(self);
Guard.IsNotNull(key);
Guard.IsNotNull(updateValueFactory);

TValue newValue;
#if NET8_0_OR_GREATER
ref var value = ref CollectionsMarshal.GetValueRefOrAddDefault(self, key, out var exists);
if (exists)
{
value = updateValueFactory(key, value!);
}
else
{
value = addValue;
}
#else
TValue value;
if (self.TryGetValue(key, out var oldValue))
{
newValue = updateValueFactory(key, oldValue);
self[key] = newValue;
value = updateValueFactory(key, oldValue);
self[key] = value;
}
else
{
newValue = addValue;
self.Add(key, newValue);
value = addValue;
self.Add(key, value);
}
return newValue;
#endif
return value;
}

/// <summary>
Expand All @@ -135,22 +163,33 @@ Func<TKey, TValue, TValue> updateValueFactory
where TKey : notnull
{
Guard.IsNotNull(self);
Guard.IsNotNull(key);
Guard.IsNotNull(addValueFactory);
Guard.IsNotNull(updateValueFactory);

TValue newValue;
#if NET8_0_OR_GREATER
ref var value = ref CollectionsMarshal.GetValueRefOrAddDefault(self, key, out var exists);
if (exists)
{
value = updateValueFactory(key, value!);
}
else
{
value = addValueFactory(key);
}
#else
TValue value;
if (self.TryGetValue(key, out var oldValue))
{
newValue = updateValueFactory(key, oldValue);
self[key] = newValue;
value = updateValueFactory(key, oldValue);
self[key] = value;
}
else
{
newValue = addValueFactory(key);
self.Add(key, newValue);
value = addValueFactory(key);
self.Add(key, value);
}
return newValue;
#endif
return value;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@
Guard.IsNotNull(assembly);

using var stream = assembly.GetEmbeddedResourceStream(resourceName);
Guard.IsNotNull(stream, nameof(resourceName));

Check warning on line 50 in CommonNet.Extensions/System.Reflection/EmbeddedResourceStreamReader.cs

View workflow job for this annotation

GitHub Actions / linux-build

Remove this argument from the method call; it hides the caller information. (https://rules.sonarsource.com/csharp/RSPEC-3236)

Check warning on line 50 in CommonNet.Extensions/System.Reflection/EmbeddedResourceStreamReader.cs

View workflow job for this annotation

GitHub Actions / linux-build

Remove this argument from the method call; it hides the caller information. (https://rules.sonarsource.com/csharp/RSPEC-3236)

var data = new byte[stream.Length];
stream.Read(data, 0, data.Length);
_ = stream.Read(data, 0, data.Length);
return data;
}

Expand All @@ -66,7 +66,7 @@
Guard.IsNotNull(assembly);

using var stream = assembly.GetEmbeddedResourceStream(resourceName);
Guard.IsNotNull(stream, nameof(resourceName));

Check warning on line 69 in CommonNet.Extensions/System.Reflection/EmbeddedResourceStreamReader.cs

View workflow job for this annotation

GitHub Actions / linux-build

Remove this argument from the method call; it hides the caller information. (https://rules.sonarsource.com/csharp/RSPEC-3236)

Check warning on line 69 in CommonNet.Extensions/System.Reflection/EmbeddedResourceStreamReader.cs

View workflow job for this annotation

GitHub Actions / linux-build

Remove this argument from the method call; it hides the caller information. (https://rules.sonarsource.com/csharp/RSPEC-3236)

encoding ??= Encoding.UTF8;
using var reader = new StreamReader(stream, encoding);
Expand Down Expand Up @@ -95,7 +95,7 @@
Guard.IsNotNull(assembly);

using var stream = assembly.GetEmbeddedResourceStream(resourceName);
Guard.IsNotNull(stream, nameof(resourceName));

Check warning on line 98 in CommonNet.Extensions/System.Reflection/EmbeddedResourceStreamReader.cs

View workflow job for this annotation

GitHub Actions / linux-build

Remove this argument from the method call; it hides the caller information. (https://rules.sonarsource.com/csharp/RSPEC-3236)

Check warning on line 98 in CommonNet.Extensions/System.Reflection/EmbeddedResourceStreamReader.cs

View workflow job for this annotation

GitHub Actions / linux-build

Remove this argument from the method call; it hides the caller information. (https://rules.sonarsource.com/csharp/RSPEC-3236)

encoding ??= Encoding.UTF8;
using var reader = new StreamReader(stream, encoding);
Expand Down
Loading
Loading