Skip to content

Commit c408f04

Browse files
committed
feat: target .netstandard 2.0
1 parent 6c42551 commit c408f04

29 files changed

+194
-38
lines changed

.editorconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,4 @@ dotnet_naming_style.begins_with_i.capitalization = pascal_case
235235

236236
[*.{cs,vb}]
237237
dotnet_diagnostic.CA1014.severity = none
238+
dotnet_diagnostic.CA1510.severity = none # disabled because we are multi targeting frameworks that does not have ANE.ThrowIfNull

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.7.0]
11+
12+
- Add support for libraries that target netstandard 2.0.
13+
1014
## [0.6.0]
1115

1216
- Changed `TestTimeProvider` to `ManualTimeProvider`.

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Time Scheduler - a TimeProvider shim
22

3-
This is a shim for the upcoming `System.TimeProvider` API coming in .NET 8. It includes a test version of the `TimeProvider`, named `ManualTimeProvider`, that allows you to control the progress of time during testing deterministically.
3+
This is a shim for the upcoming `System.TimeProvider` API coming in .NET 8. It includes a test version of the `TimeProvider` type, named `ManualTimeProvider`, that allows you to control the progress of time during testing deterministically.
44

55
*NOTE: Originally, this library provided its own abstraction, `ITimeScheduler` and related types, `DefaultScheduler` and `TestScheduler`. These are now considered obsolete.*
66

@@ -10,11 +10,11 @@ Currently, the following .NET time-based APIs are supported:
1010
|----------------------|----------------------|
1111
| `GetUtcNow()` method | `DateTimeOffset.UtcNow` property |
1212
| `CreateTimer()` method | `System.Threading.Timer` type |
13-
| `CreatePeriodicTimer(TimeSpan)` method | `System.Threading.PeriodicTimer` type |
13+
| `CreatePeriodicTimer(TimeSpan)` method (only .NET 6) | `System.Threading.PeriodicTimer` type |
1414
| `Delay(TimeSpan, CancellationToken)` method | `Task.Delay(TimeSpan, CancellationToken)` method |
1515
| `CancellationTokenSource.CancelAfter(TimeSpan, TimeProvider)` method | `CancellationTokenSource.CancelAfter(TimeSpan)` method |
16-
| `Task.WaitAsync(TimeSpan, TimeProvider)` method | `Task.WaitAsync(TimeSpan)` method |
17-
| `Task.WaitAsync(TimeSpan, TimeProvider, CancellationToken)` method | `Task.WaitAsync(TimeSpan, CancellationToken)` method |
16+
| `Task.WaitAsync(TimeSpan, TimeProvider)` method (only .NET 6)| `Task.WaitAsync(TimeSpan)` method |
17+
| `Task.WaitAsync(TimeSpan, TimeProvider, CancellationToken)` method (only .NET 6)| `Task.WaitAsync(TimeSpan, CancellationToken)` method |
1818

1919
The implementations of `TimeProvider` is abstract. An instance of `TimeProvider` for production use is availalbe on the `TimeProvider.System` property,
2020
and `ManualTimeProvider` can be used during testing.

TimeScheduler.sln

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1111
ProjectSection(SolutionItems) = preProject
1212
.editorconfig = .editorconfig
1313
CHANGELOG.md = CHANGELOG.md
14-
global.json = global.json
1514
README.md = README.md
1615
EndProjectSection
1716
EndProject

src/TimeScheduler/DefaultScheduler.cs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ public partial class DefaultScheduler : TimeProvider, ITimeScheduler
2929
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3030
public void CancelAfter(CancellationTokenSource cancellationTokenSource, TimeSpan delay)
3131
{
32-
ArgumentNullException.ThrowIfNull(cancellationTokenSource);
32+
if (cancellationTokenSource is null)
33+
{
34+
throw new ArgumentNullException(nameof(cancellationTokenSource));
35+
}
36+
3337
cancellationTokenSource.CancelAfter(delay);
3438
}
3539

@@ -43,6 +47,7 @@ public Task Delay(TimeSpan delay)
4347
public Task Delay(TimeSpan delay, CancellationToken cancellationToken)
4448
=> Task.Delay(delay, cancellationToken);
4549

50+
#if NET6_0_OR_GREATER
4651
/// <inheritdoc/>
4752
[MethodImpl(MethodImplOptions.AggressiveInlining)]
4853
public PeriodicTimer PeriodicTimer(TimeSpan period)
@@ -52,31 +57,48 @@ public PeriodicTimer PeriodicTimer(TimeSpan period)
5257
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5358
public Task WaitAsync(Task task, TimeSpan timeout)
5459
{
55-
ArgumentNullException.ThrowIfNull(task);
60+
if (task is null)
61+
{
62+
throw new ArgumentNullException(nameof(task));
63+
}
64+
5665
return task.WaitAsync(timeout);
5766
}
5867

5968
/// <inheritdoc/>
6069
[MethodImpl(MethodImplOptions.AggressiveInlining)]
6170
public Task WaitAsync(Task task, TimeSpan timeout, CancellationToken cancellationToken)
6271
{
63-
ArgumentNullException.ThrowIfNull(task);
72+
if (task is null)
73+
{
74+
throw new ArgumentNullException(nameof(task));
75+
}
76+
6477
return task.WaitAsync(timeout, cancellationToken);
6578
}
6679

6780
/// <inheritdoc/>
6881
[MethodImpl(MethodImplOptions.AggressiveInlining)]
6982
public Task<TResult> WaitAsync<TResult>(Task<TResult> task, TimeSpan timeout)
7083
{
71-
ArgumentNullException.ThrowIfNull(task);
84+
if (task is null)
85+
{
86+
throw new ArgumentNullException(nameof(task));
87+
}
88+
7289
return task.WaitAsync(timeout);
7390
}
7491

7592
/// <inheritdoc/>
7693
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7794
public Task<TResult> WaitAsync<TResult>(Task<TResult> task, TimeSpan timeout, CancellationToken cancellationToken)
7895
{
79-
ArgumentNullException.ThrowIfNull(task);
96+
if (task is null)
97+
{
98+
throw new ArgumentNullException(nameof(task));
99+
}
100+
80101
return task.WaitAsync(timeout, cancellationToken);
81102
}
103+
#endif
82104
}

src/TimeScheduler/ITimeScheduler.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public interface ITimeScheduler
2323
/// <remarks>
2424
/// The default implementation returns <see cref="DateTimeOffset.UtcNow"/>.
2525
/// </remarks>
26-
public virtual DateTimeOffset GetUtcNow() => DateTimeOffset.UtcNow;
26+
DateTimeOffset GetUtcNow();
2727

2828
/// <summary>
2929
/// Creates a Task that will complete after a time delay.
@@ -60,6 +60,7 @@ public interface ITimeScheduler
6060
/// </remarks>
6161
Task Delay(TimeSpan delay, CancellationToken cancellationToken);
6262

63+
#if NET6_0_OR_GREATER
6364
/// <summary>
6465
/// Factory method that creates a periodic timer that enables waiting asynchronously for timer ticks.
6566
/// Use this factory method as a replacement for instantiating a <see cref="System.Threading.PeriodicTimer"/>.
@@ -115,6 +116,7 @@ public interface ITimeScheduler
115116
/// <exception cref="ArgumentNullException">The <paramref name="task"/> is null.</exception>
116117
/// <returns>The <see cref="Task{TResult}"/> representing the asynchronous wait. It may or may not be the same instance as the current instance.</returns>
117118
Task<TResult> WaitAsync<TResult>(Task<TResult> task, TimeSpan timeout, CancellationToken cancellationToken);
119+
#endif
118120

119121
/// <summary>
120122
/// Schedules a Cancel operation on the <paramref name="cancellationTokenSource"/>.

src/TimeScheduler/PeriodicTimerWrapper.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#if NET6_0_OR_GREATER
12
namespace TimeScheduler;
23

34
internal sealed class PeriodicTimerWrapper : PeriodicTimer
@@ -18,3 +19,4 @@ protected override void Dispose(bool disposing)
1819
base.Dispose(disposing);
1920
}
2021
}
22+
#endif
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#if !NET6_0_OR_GREATER
2+
namespace System.Runtime.CompilerServices;
3+
4+
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
5+
internal sealed class CallerArgumentExpressionAttribute : Attribute
6+
{
7+
public CallerArgumentExpressionAttribute(string parameterName)
8+
{
9+
ParameterName = parameterName;
10+
}
11+
12+
public string ParameterName { get; }
13+
}
14+
#endif

src/TimeScheduler/System/Testing/TestPeriodicTimer.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#if NET6_0_OR_GREATER
12
namespace System.Testing;
23

34
internal sealed class TestPeriodicTimer : TimeScheduler.PeriodicTimer
@@ -62,3 +63,4 @@ protected override void Dispose(bool disposing)
6263
base.Dispose(disposing);
6364
}
6465
}
66+
#endif

src/TimeScheduler/System/Threading/ITimer.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
namespace System.Threading;
22

3+
#if NET6_0_OR_GREATER
34
/// <summary>Represents a timer that can have its due time and period changed.</summary>
45
/// <remarks>
56
/// Implementations of <see cref="Change"/>, <see cref="IDisposable.Dispose"/>, and <see cref="IAsyncDisposable.DisposeAsync"/>
67
/// must all be thread-safe such that the timer instance may be accessed concurrently from multiple threads.
78
/// </remarks>
8-
public interface ITimer : IDisposable, IAsyncDisposable
9+
#else
10+
/// <summary>Represents a timer that can have its due time and period changed.</summary>
11+
/// <remarks>
12+
/// Implementations of <see cref="Change"/> and <see cref="IDisposable.Dispose"/>
13+
/// must all be thread-safe such that the timer instance may be accessed concurrently from multiple threads.
14+
/// </remarks>
15+
#endif
16+
public interface ITimer : IDisposable
17+
#if NET6_0_OR_GREATER
18+
, IAsyncDisposable
19+
#endif
920
{
1021
/// <summary>Changes the start time and the interval between method invocations for a timer, using <see cref="TimeSpan"/> values to measure time intervals.</summary>
1122
/// <param name="dueTime">

0 commit comments

Comments
 (0)