From 812698b5e81818bb81e3d7b2f92a746a15ac3942 Mon Sep 17 00:00:00 2001 From: Matthew Layton Date: Fri, 31 Jan 2025 12:02:00 +0000 Subject: [PATCH] Added `ToOptional` and `ToOptionalAsync` methods that work with reference types and value types, and renamed `ToSuccessResult` and `ToSuccessResultAsync` to `ToSuccess` and `ToSuccessAsync` respectively. --- Directory.Build.props | 6 +- .../ObjectExtensionTests.cs | 120 +++++++++++++++++- OnixLabs.Core/Extensions.Object.cs | 40 +++++- 3 files changed, 155 insertions(+), 11 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 094a495..9ca331a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -8,8 +8,8 @@ en Copyright © ONIXLabs 2020 https://github.com/onix-labs/onixlabs-dotnet - 11.3.0 - 11.3.0 - 11.3.0 + 12.0.0 + 12.0.0 + 12.0.0 diff --git a/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs b/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs index 8c4a0cc..8d73668 100644 --- a/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs @@ -225,29 +225,137 @@ public void ToStringOrNullShouldProduceExpectedResultWhenObjectIsNotNull() Assert.Equal(expected, actual); } - [Fact(DisplayName = "ToSuccessResult should produce the expected result")] - public void ToSuccessResultShouldProduceTheExpectedResult() + [Fact(DisplayName = "ToOptional should produce the expected result when using a non-null reference type")] + public void ToOptionalShouldProduceExpectedResultWhenUsingNonNullReferenceType() { // Given const string expected = "abc"; // When - Result result = expected.ToSuccessResult(); + Optional optional = expected.ToOptional(); + + // Then + Some some = Assert.IsType>(optional); + Assert.Equal(expected, some.Value); + } + + [Fact(DisplayName = "ToOptional should produce the expected result when using a null reference type")] + public void ToOptionalShouldProduceExpectedResultWhenUsingNullReferenceType() + { + // Given + const string? expected = null; + + // When + Optional optional = expected.ToOptional(); + + // Then + Assert.IsType>(optional); + } + + [Fact(DisplayName = "ToOptional should produce the expected result when using a non-null value type")] + public void ToOptionalShouldProduceExpectedResultWhenUsingNonNullValueType() + { + // Given + const int expected = 123; + + // When + Optional optional = expected.ToOptional(); + + // Then + Some some = Assert.IsType>(optional); + Assert.Equal(expected, some.Value); + } + + [Fact(DisplayName = "ToOptional should produce the expected result when using a null value type")] + public void ToOptionalShouldProduceExpectedResultWhenUsingNullValueType() + { + // Given + int? expected = null; + + // When + Optional optional = expected.ToOptional(); + + // Then + Assert.IsType>(optional); + } + + [Fact(DisplayName = "ToOptionalAsync should produce the expected result when using a non-null reference type")] + public async Task ToOptionalAsyncShouldProduceExpectedResultWhenUsingNonNullReferenceType() + { + // Given + const string expected = "abc"; + + // When + Optional optional = await Task.FromResult(expected).ToOptionalAsync(); + + // Then + Some some = Assert.IsType>(optional); + Assert.Equal(expected, some.Value); + } + + [Fact(DisplayName = "ToOptionalAsync should produce the expected result when using a null reference type")] + public async Task ToOptionalAsyncShouldProduceExpectedResultWhenUsingNullReferenceType() + { + // Given + const string? expected = null; + + // When + Optional optional = await Task.FromResult(expected).ToOptionalAsync(); + + // Then + Assert.IsType>(optional); + } + + [Fact(DisplayName = "ToOptionalAsync should produce the expected result when using a non-null value type")] + public async Task ToOptionalAsyncShouldProduceExpectedResultWhenUsingNonNullValueType() + { + // Given + const int expected = 123; + + // When + Optional optional = await Task.FromResult(expected).ToOptionalAsync(); + + // Then + Some some = Assert.IsType>(optional); + Assert.Equal(expected, some.Value); + } + + [Fact(DisplayName = "ToOptionalAsync should produce the expected result when using a null value type")] + public async Task ToOptionalAsyncShouldProduceExpectedResultWhenUsingNullValueType() + { + // Given + int? expected = null; + + // When + Optional optional = await Task.FromResult(expected).ToOptionalAsync(); + + // Then + Assert.IsType>(optional); + } + + [Fact(DisplayName = "ToSuccess should produce the expected result")] + public void ToSuccessShouldProduceTheExpectedResult() + { + // Given + const string expected = "abc"; + + // When + Result result = expected.ToSuccess(); // Then Success success = Assert.IsType>(result); Assert.Equal(expected, success.Value); } - [Fact(DisplayName = "ToSuccessResultAsync should produce the expected result")] - public async Task ToSuccessResultAsyncShouldProduceTheExpectedResult() + [Fact(DisplayName = "ToSuccessAsync should produce the expected result")] + public async Task ToSuccessAsyncShouldProduceTheExpectedResult() { // Given const string expected = "abc"; // When Task task = Task.FromResult(expected); - Result result = await task.ToSuccessResultAsync(); + Result result = await task.ToSuccessAsync(); // Then Success success = Assert.IsType>(result); diff --git a/OnixLabs.Core/Extensions.Object.cs b/OnixLabs.Core/Extensions.Object.cs index 5d38c67..37a9145 100644 --- a/OnixLabs.Core/Extensions.Object.cs +++ b/OnixLabs.Core/Extensions.Object.cs @@ -173,13 +173,49 @@ public static string ToRecordString(this object? value) /// Returns a representation of the current , or a string literal null if the current object is . public static string ToStringOrNull(this object? value) => value?.ToString() ?? Null; + /// + /// Obtains an representation of the current . + /// + /// The to wrap as an value. + /// The underlying type of the value. + /// Returns an representation of the current . + public static Optional ToOptional(this T? value) where T : notnull => Optional.Of(value); + + /// + /// Obtains an representation of the current . + /// + /// The to wrap as an value. + /// The underlying type of the value. + /// Returns an representation of the current . + public static Optional ToOptional(this T? value) where T : struct => Optional.Of(value); + + /// + /// Asynchronously obtains an representation of the current . + /// + /// The to wrap as an value. + /// /// The cancellation token that can be used to cancel long-running tasks. + /// The underlying type of the value. + /// Returns an representation of the current . + public static async Task> ToOptionalAsync(this Task value, CancellationToken token = default) where T : notnull => + Optional.Of(await value.WaitAsync(token).ConfigureAwait(false)); + + /// + /// Asynchronously obtains an representation of the current . + /// + /// The to wrap as an value. + /// /// The cancellation token that can be used to cancel long-running tasks. + /// The underlying type of the value. + /// Returns an representation of the current . + public static async Task> ToOptionalAsync(this Task value, CancellationToken token = default) where T : struct => + Optional.Of(await value.WaitAsync(token).ConfigureAwait(false)); + /// /// Obtains a representation of the current . /// /// The to wrap as a result. /// The underlying type of the value. /// Returns a representation of the current . - public static Result ToSuccessResult(this T value) => Result.Success(value); + public static Success ToSuccess(this T value) => Result.Success(value); /// /// Asynchronously obtains a representation of the current . @@ -188,6 +224,6 @@ public static string ToRecordString(this object? value) /// The cancellation token that can be used to cancel long-running tasks. /// The underlying type of the value. /// Returns a representation of the current . - public static async Task> ToSuccessResultAsync(this Task value, CancellationToken token = default) => + public static async Task> ToSuccessAsync(this Task value, CancellationToken token = default) => Result.Success(await value.WaitAsync(token).ConfigureAwait(false)); }