diff --git a/PolyShim.Tests/NetCore10/ProgressTests.cs b/PolyShim.Tests/NetCore10/ProgressTests.cs new file mode 100644 index 00000000..03958181 --- /dev/null +++ b/PolyShim.Tests/NetCore10/ProgressTests.cs @@ -0,0 +1,61 @@ +using System; +using System.Threading; +using FluentAssertions; +using Xunit; + +namespace PolyShim.Tests.NetCore10; + +public class ProgressTests +{ + [Fact] + public void Report_WithHandler_Test() + { + // Arrange + using var received = new ManualResetEventSlim(); + var receivedValue = default(int); + var progress = new Progress(v => + { + receivedValue = v; + received.Set(); + }); + + // Act + ((IProgress)progress).Report(42); + + // Assert + received.Wait(TimeSpan.FromSeconds(5)).Should().BeTrue(); + receivedValue.Should().Be(42); + } + + [Fact] + public void Report_WithEvent_Test() + { + // Arrange + using var received = new ManualResetEventSlim(); + var receivedValue = default(int); + var progress = new Progress(); + progress.ProgressChanged += (_, v) => + { + receivedValue = v; + received.Set(); + }; + + // Act + ((IProgress)progress).Report(99); + + // Assert + received.Wait(TimeSpan.FromSeconds(5)).Should().BeTrue(); + receivedValue.Should().Be(99); + } + + [Fact] + public void Report_NoHandler_Test() + { + // Arrange + var progress = new Progress(); + + // Act & assert + var act = () => ((IProgress)progress).Report(1); + act.Should().NotThrow(); + } +} diff --git a/PolyShim/NetCore10/EventHandler.cs b/PolyShim/NetCore10/EventHandler.cs new file mode 100644 index 00000000..68d8056e --- /dev/null +++ b/PolyShim/NetCore10/EventHandler.cs @@ -0,0 +1,9 @@ +#if NETFRAMEWORK && !NET45_OR_GREATER +#nullable enable +#pragma warning disable CS0436 + +namespace System; + +// https://learn.microsoft.com/dotnet/api/system.eventhandler-1 +internal delegate void EventHandler(object sender, TEventArgs e); +#endif diff --git a/PolyShim/NetCore10/IProgress.cs b/PolyShim/NetCore10/IProgress.cs new file mode 100644 index 00000000..5a818c70 --- /dev/null +++ b/PolyShim/NetCore10/IProgress.cs @@ -0,0 +1,12 @@ +#if (NETFRAMEWORK && !NET45_OR_GREATER) || (NETSTANDARD && !NETSTANDARD1_1_OR_GREATER) +#nullable enable +#pragma warning disable CS0436 + +namespace System; + +// https://learn.microsoft.com/dotnet/api/system.iprogress-1 +internal interface IProgress +{ + void Report(T value); +} +#endif diff --git a/PolyShim/NetCore10/Progress.cs b/PolyShim/NetCore10/Progress.cs new file mode 100644 index 00000000..688cfcd3 --- /dev/null +++ b/PolyShim/NetCore10/Progress.cs @@ -0,0 +1,50 @@ +#if (NETFRAMEWORK && !NET45_OR_GREATER) || (NETSTANDARD && !NETSTANDARD1_3_OR_GREATER) +#nullable enable +#pragma warning disable CS0436 + +using System.Diagnostics.CodeAnalysis; +using System.Threading; + +namespace System; + +// https://learn.microsoft.com/dotnet/api/system.progress-1 +#if !POLYSHIM_INCLUDE_COVERAGE +[ExcludeFromCodeCoverage] +#endif +internal class Progress : IProgress +{ + private readonly SynchronizationContext _synchronizationContext; + private readonly Action? _handler; + + public event EventHandler? ProgressChanged; + + public Progress() + { + _synchronizationContext = SynchronizationContext.Current ?? new(); + } + + public Progress(Action handler) + : this() => _handler = handler; + + protected virtual void OnReport(T value) + { + var handler = _handler; + var progressChanged = ProgressChanged; + + if (handler is not null || progressChanged is not null) + { + _synchronizationContext.Post( + s => + { + var (v, h, e) = ((T, Action?, EventHandler?))s!; + h?.Invoke(v); + e?.Invoke(this, v); + }, + (value, handler, progressChanged) + ); + } + } + + void IProgress.Report(T value) => OnReport(value); +} +#endif diff --git a/Signatures.md b/Signatures.md index b4836cac..82afcca4 100644 --- a/Signatures.md +++ b/Signatures.md @@ -1,7 +1,7 @@ # Signatures -- **Total:** 488 -- **Types:** 106 +- **Total:** 491 +- **Types:** 109 - **Members:** 382 ___ @@ -122,6 +122,8 @@ ___ - [`static string? ProcessPath`](https://learn.microsoft.com/dotnet/api/system.environment.processpath) .NET 6.0 - `EqualityComparer` - [`static EqualityComparer Create(Func, Func?)`](https://learn.microsoft.com/dotnet/api/system.collections.generic.equalitycomparer-1.create) .NET 8.0 +- `EventHandler` + - [**[delegate]**](https://learn.microsoft.com/dotnet/api/system.eventhandler-1) .NET Core 1.0 - `ExcludeFromCodeCoverageAttribute` - [**[class]**](https://learn.microsoft.com/dotnet/api/system.diagnostics.codeanalysis.excludefromcodecoverageattribute) .NET Core 2.0 - `ExtensionAttribute` @@ -260,6 +262,8 @@ ___ - [`static IntPtr Parse(string, IFormatProvider?)`](https://learn.microsoft.com/dotnet/api/system.intptr.parse#system-intptr-parse(system-string-system-iformatprovider)) .NET 5.0 - [`static IntPtr Parse(string, NumberStyles)`](https://learn.microsoft.com/dotnet/api/system.intptr.parse#system-intptr-parse(system-string-system-globalization-numberstyles)) .NET 5.0 - [`static IntPtr Parse(string, NumberStyles, IFormatProvider?)`](https://learn.microsoft.com/dotnet/api/system.intptr.parse#system-intptr-parse(system-string-system-globalization-numberstyles-system-iformatprovider)) .NET 5.0 +- `IProgress` + - [**[interface]**](https://learn.microsoft.com/dotnet/api/system.iprogress-1) .NET Core 1.0 - `IReadOnlyDictionary` - [`TValue? GetValueOrDefault(TKey)`](https://learn.microsoft.com/dotnet/api/system.collections.generic.collectionextensions.getvalueordefault#system-collections-generic-collectionextensions-getvalueordefault-2(system-collections-generic-ireadonlydictionary((-0-1))-0)) .NET Core 2.0 - [`TValue? GetValueOrDefault(TKey, TValue?)`](https://learn.microsoft.com/dotnet/api/system.collections.generic.collectionextensions.getvalueordefault#system-collections-generic-collectionextensions-getvalueordefault-2(system-collections-generic-ireadonlydictionary((-0-1))-0-1)) .NET Core 2.0 @@ -372,6 +376,8 @@ ___ - [`bool WaitForExit(TimeSpan)`](https://learn.microsoft.com/dotnet/api/system.diagnostics.process.waitforexit#system-diagnostics-process-waitforexit(system-timespan)) .NET 7.0 - [`Task WaitForExitAsync(CancellationToken)`](https://learn.microsoft.com/dotnet/api/system.diagnostics.process.waitforexitasync) .NET 5.0 - [`void Kill(bool)`](https://learn.microsoft.com/dotnet/api/system.diagnostics.process.kill#system-diagnostics-process-kill(system-boolean)) .NET Core 3.0 +- `Progress` + - [**[class]**](https://learn.microsoft.com/dotnet/api/system.progress-1) .NET Core 1.0 - `Queue` - [`bool TryDequeue(out T?)`](https://learn.microsoft.com/dotnet/api/system.collections.generic.queue-1.trydequeue) .NET Core 2.0 - [`bool TryPeek(out T?)`](https://learn.microsoft.com/dotnet/api/system.collections.generic.queue-1.trypeek) .NET Core 2.0