diff --git a/SystemExtensions.NetCore/SystemExtensions.NetCore.csproj b/SystemExtensions.NetCore/SystemExtensions.NetCore.csproj index 70a3f87..dfd1b66 100644 --- a/SystemExtensions.NetCore/SystemExtensions.NetCore.csproj +++ b/SystemExtensions.NetCore/SystemExtensions.NetCore.csproj @@ -8,7 +8,7 @@ System LICENSE true - 1.8 + 1.9 Alexandru Macocian https://github.com/AlexMacocian/SystemExtensions Extensions for the System namespace diff --git a/SystemExtensions.NetStandard/Extensions/ObjectExtensions.cs b/SystemExtensions.NetStandard/Extensions/ObjectExtensions.cs index 0035c12..02d7903 100644 --- a/SystemExtensions.NetStandard/Extensions/ObjectExtensions.cs +++ b/SystemExtensions.NetStandard/Extensions/ObjectExtensions.cs @@ -1,31 +1,7 @@ -using Newtonsoft.Json; - -namespace System.Extensions; +namespace System.Extensions; public static class ObjectExtensions { - public static T? Deserialize(this string serialized) - where T : class - { - if (serialized.IsNullOrWhiteSpace()) - { - throw new ArgumentException("Provided serialized string cannot be null or whitespace", nameof(serialized)); - } - - return JsonConvert.DeserializeObject(serialized); - } - - public static string Serialize(this T obj) - where T : class - { - if (obj is null) - { - throw new ArgumentNullException(nameof(obj)); - } - - return JsonConvert.SerializeObject(obj); - } - public static T Cast(this object obj) { return (T)obj; @@ -36,11 +12,6 @@ public static class ObjectExtensions return obj as T; } - public static Optional ToOptional(this T obj) - { - return Optional.FromValue(obj); - } - public static T ThrowIfNull([ValidatedNotNull] this T? obj, string name) where T : class { if (obj is null) diff --git a/SystemExtensions.NetStandard/Extensions/Optional.cs b/SystemExtensions.NetStandard/Extensions/Optional.cs deleted file mode 100644 index 6900288..0000000 --- a/SystemExtensions.NetStandard/Extensions/Optional.cs +++ /dev/null @@ -1,193 +0,0 @@ -namespace System.Extensions; - -public static class Optional -{ - public static Optional None() - { - return new Optional.None(); - } - - public static Optional FromValue(T? value) - { - if (value == null) - { - return new Optional.None(); - } - - return new Optional.Some(value); - } -} - -public abstract class Optional : IEquatable> -{ - public Optional(T value) - { - this.Value = value; - } - - private T Value { get; } - - public T? ExtractValue() - { - if (this is None) - { - return default; - } - else - { - return this.Value; - } - } - public Optional Do(Action? onSome, Action? onNone) - { - if (onSome is null) - { - throw new ArgumentNullException(nameof(onSome)); - } - - if (onNone is null) - { - throw new ArgumentNullException(nameof(onNone)); - } - - if (this is Some) - { - onSome.Invoke(this.Value); - } - else - { - onNone.Invoke(); - } - - return this; - } - public Optional DoAny(Action? onSome = default, Action? onNone = default) - { - if (this is Some) - { - onSome?.Invoke(this.Value); - } - else - { - onNone?.Invoke(); - } - - return this; - } - public Optional Switch(Func? onSome, Func? onNone) - { - if (onSome is null) - { - throw new ArgumentNullException($"{nameof(onSome)}"); - } - - if (onNone is null) - { - throw new ArgumentNullException($"{nameof(onNone)}"); - } - - if (this is Some) - { - return Optional.FromValue(onSome.Invoke(this.Value)); - } - else - { - return Optional.FromValue(onNone.Invoke()); - } - } - public Optional SwitchAny(Func? onSome = null, Func? onNone = null) - { - if (this is Some) - { - return onSome != null ? Optional.FromValue(onSome.Invoke(this.Value)) : Optional.FromValue(default(V)); - } - else - { - return onNone != null ? Optional.FromValue(onNone.Invoke()) : Optional.FromValue(default(V)); - } - } - - public override bool Equals(object? obj) - { - if (obj is Optional) - { - return this.Equals(obj); - } - - return base.Equals(obj); - } - - public bool Equals(Optional? other) - { - if (this is Some && other is Some) - { - return this.As() is Some some ? some.Equals(other.As()) : false; - } - - return false; - } - - public static implicit operator Optional(T? value) - { - return Optional.FromValue(value); - } - - public override int GetHashCode() - { - return this.Value == null ? base.GetHashCode() : this.Value.GetHashCode(); - } - - internal class Some : Optional, IEquatable - { - public Some(T value) : base(value) - { - } - - public override bool Equals(object? obj) - { - if (obj is Some) - { - return this.Equals(obj.As()); - } - - return base.Equals(obj); - } - - public bool Equals(Some? other) - { - if (other is None) - { - return false; - } - - if (other is not null) - { - return this.Value is not null && this.Value.Equals(other.Value); - } - - return false; - } - - public static bool operator ==(Some? left, Some right) - { - return left?.Equals(right) == true; - } - - public static bool operator !=(Some? left, Some right) - { - return left?.Equals(right) != true; - } - - public override int GetHashCode() - { - return this.Value is object ? this.Value.GetHashCode() : this.As() is object obj ? obj.GetHashCode() : 0; - } - } - - internal class None : Optional - { - public None() : base(default!) - { - } - } -} diff --git a/SystemExtensions.NetStandard/Extensions/Result.cs b/SystemExtensions.NetStandard/Extensions/Result.cs deleted file mode 100644 index 63ad0f2..0000000 --- a/SystemExtensions.NetStandard/Extensions/Result.cs +++ /dev/null @@ -1,216 +0,0 @@ -namespace System.Extensions; - -public class Result -{ - private readonly object? value; - - public Result(TSuccess successValue) - { - this.value = successValue; - } - public Result(TFailure failureValue) - { - this.value = failureValue; - } - - public bool TryExtractSuccess(out TSuccess? successValue) - { - - if (this.value is TSuccess success) - { - successValue = success; - return true; - } - else - { - successValue = default; - return false; - } - } - public bool TryExtractFailure(out TFailure? failureValue) - { - - if (this.value is TFailure failure) - { - failureValue = failure; - return true; - } - else - { - failureValue = default; - return false; - } - } - public Result Do(Action onSuccess, Action onFailure) - { - if (onSuccess is null) - { - throw new ArgumentNullException(nameof(onSuccess)); - } - - if (onFailure is null) - { - throw new ArgumentNullException(nameof(onFailure)); - } - - if (this.value is TSuccess) - { - onSuccess.Invoke(); - } - else if (this.value is TFailure) - { - onFailure.Invoke(); - } - - return this; - } - public Result DoAny(Action? onSuccess = null, Action? onFailure = null) - { - if (this.value is TSuccess) - { - onSuccess?.Invoke(); - } - else if (this.value is TFailure) - { - onFailure?.Invoke(); - } - - return this; - } - public Result Do(Action onSuccess, Action onFailure) - { - if (onSuccess is null) - { - throw new ArgumentNullException(nameof(onSuccess)); - } - - if (onFailure is null) - { - throw new ArgumentNullException(nameof(onFailure)); - } - - if (this.value is TSuccess success) - { - onSuccess.Invoke(success); - } - else if (this.value is TFailure failure) - { - onFailure.Invoke(failure); - } - - return this; - } - public Result DoAny(Action? onSuccess = null, Action? onFailure = null) - { - if (this.value is TSuccess success) - { - onSuccess?.Invoke(success); - } - else if (this.value is TFailure failure) - { - onFailure?.Invoke(failure); - } - - return this; - } - public T Switch(Func onSuccess, Func onFailure) - { - if (onSuccess is null) - { - throw new ArgumentNullException(nameof(onSuccess)); - } - - if (onFailure is null) - { - throw new ArgumentNullException(nameof(onFailure)); - } - - if (this.value is TSuccess success) - { - return onSuccess.Invoke(success); - } - else if (this.value is TFailure failure) - { - return onFailure.Invoke(failure); - } - - throw new InvalidOperationException($"{nameof(this.value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to {typeof(T)}"); - } - public T? SwitchAny(Func? onSuccess = null, Func? onFailure = null) - { - if (this.value is TSuccess success) - { - return onSuccess is null ? default : onSuccess.Invoke(success); - } - else if (this.value is TFailure failure) - { - return onFailure is null ? default : onFailure.Invoke(failure); - } - - throw new InvalidOperationException($"{nameof(this.value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to {typeof(T)}"); - } - public Result Switch(Func onSuccess, Func onFailure) - { - if (onSuccess is null) - { - throw new ArgumentNullException(nameof(onSuccess)); - } - - if (onFailure is null) - { - throw new ArgumentNullException(nameof(onFailure)); - } - - if (this.value is TSuccess success) - { - return Result.Success(onSuccess.Invoke(success)); - } - else if (this.value is TFailure failure) - { - return Result.Failure(onFailure.Invoke(failure)); - } - - throw new InvalidOperationException($"{nameof(this.value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to Result of type {typeof(V)} or {typeof(K)}"); - } - public Result SwitchAny(Func onSuccess, Func onFailure) - { - if (this.value is TSuccess success) - { - return Result.Success(onSuccess is not null ? onSuccess.Invoke(success) : default!); - } - else if (this.value is TFailure failure) - { - return Result.Failure(onFailure is not null ? onFailure.Invoke(failure) : default!); - } - - throw new InvalidOperationException($"{nameof(this.value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to Result of type {typeof(V)} or {typeof(K)}"); - } - public Optional ToOptional() - { - if (this.value is TSuccess) - { - return Optional.FromValue(this.value.Cast()); - } - - return Optional.None(); - } - - public static implicit operator Result(TSuccess success) - { - return Success(success); - } - - public static implicit operator Result(TFailure failure) - { - return Failure(failure); - } - - public static Result Success(TSuccess value) - { - return new Result(value); - } - public static Result Failure(TFailure value) - { - return new Result(value); - } -} diff --git a/SystemExtensions.NetStandard/Extensions/StreamExtensions.cs b/SystemExtensions.NetStandard/Extensions/StreamExtensions.cs index 5930cfe..6298b32 100644 --- a/SystemExtensions.NetStandard/Extensions/StreamExtensions.cs +++ b/SystemExtensions.NetStandard/Extensions/StreamExtensions.cs @@ -5,27 +5,6 @@ namespace System.Extensions; public static class StreamExtensions { - public static void DoWhileReading(this Stream stream, Action action, int bufferLength = 256) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (action is null) - { - throw new ArgumentNullException(nameof(action)); - } - - var buffer = new byte[bufferLength]; - var read = stream.Read(buffer, 0, bufferLength); - while(read > 0) - { - action(bufferLength, buffer); - read = stream.Read(buffer, 0, bufferLength); - } - } - public static byte[] ReadBytes(this Stream stream, int count) { if (stream is null) diff --git a/SystemExtensions.NetStandard/Extensions/TaskExtensions.cs b/SystemExtensions.NetStandard/Extensions/TaskExtensions.cs deleted file mode 100644 index 656c711..0000000 --- a/SystemExtensions.NetStandard/Extensions/TaskExtensions.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace System.Extensions; - -public static class TaskExtensions -{ - /// - /// Mark task as . - /// - /// Result type. - /// Task. - /// The started - public static Task LongRunning(this Task task) - { - return Task.Factory.StartNew(async () => - { - return await task; - }, TaskCreationOptions.LongRunning).Unwrap(); - } - - /// - /// Mark task as . - /// - /// Task. - /// The started - public static Task LongRunning(this Task task) - { - return Task.Factory.StartNew(async () => - { - await task; - }, TaskCreationOptions.LongRunning).Unwrap(); - } - - /// - /// Execute action periodically and asynchronously. - /// - /// Action to be executed. - /// Time to pass before starting to execute. - /// Interval between procs. - /// Cancellation token used to cancel the cycle. - /// - public static async Task RunPeriodicAsync(this Action onTick, TimeSpan dueTime, TimeSpan interval, CancellationToken token) - { - if (dueTime > TimeSpan.Zero) - { - await Task.Delay(dueTime, token).ConfigureAwait(false); - } - - while (!token.IsCancellationRequested) - { - onTick?.Invoke(); - if (interval > TimeSpan.Zero) - { - await Task.Delay(interval, token).ConfigureAwait(false); - } - } - } - - /// - /// Execute's an async Task method which has a void return value synchronously - /// - /// Task method to execute - public static void RunSync(this Func task) - { - var oldContext = SynchronizationContext.Current; - var synch = new ExclusiveSynchronizationContext(); - SynchronizationContext.SetSynchronizationContext(synch); - synch.Post(async _ => - { - try - { - await task(); - } - catch (Exception e) - { - synch.InnerException = e; - throw; - } - finally - { - synch.EndMessageLoop(); - } - }, default!); - synch.BeginMessageLoop(); - - SynchronizationContext.SetSynchronizationContext(oldContext); - } - - /// - /// Execute's an async Task method which has a T return type synchronously - /// - /// Return Type - /// Task method to execute - /// - public static T RunSync(this Func> task) - { - var oldContext = SynchronizationContext.Current; - var synch = new ExclusiveSynchronizationContext(); - SynchronizationContext.SetSynchronizationContext(synch); - var ret = default(T); - synch.Post(async _ => - { - try - { - ret = await task(); - } - catch (Exception e) - { - synch.InnerException = e; - throw; - } - finally - { - synch.EndMessageLoop(); - } - }, default!); - synch.BeginMessageLoop(); - SynchronizationContext.SetSynchronizationContext(oldContext); - return ret!; - } - - private class ExclusiveSynchronizationContext : SynchronizationContext - { - private bool done; - public Exception? InnerException { get; set; } - readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false); - readonly Queue> items = - new Queue>(); - - public override void Send(SendOrPostCallback d, object state) - { - throw new NotSupportedException("We cannot send to our same thread"); - } - - public override void Post(SendOrPostCallback d, object state) - { - lock (this.items) - { - this.items.Enqueue(Tuple.Create(d, state)); - } - - this.workItemsWaiting.Set(); - } - - public void EndMessageLoop() - { - this.Post(_ => this.done = true, default!); - } - - public void BeginMessageLoop() - { - while (!this.done) - { - Tuple task = default!; - lock (this.items) - { - if (this.items.Count > 0) - { - task = this.items.Dequeue(); - } - } - - if (task != null) - { - task.Item1(task.Item2); - if (this.InnerException != null) // the method threw an exeption - { - throw new AggregateException("AsyncHelpers.Run method threw an exception.", this.InnerException); - } - } - else - { - this.workItemsWaiting.WaitOne(); - } - } - } - - public override SynchronizationContext CreateCopy() - { - return this; - } - } -} diff --git a/SystemExtensions.NetStandard/SystemExtensions.NetStandard.csproj b/SystemExtensions.NetStandard/SystemExtensions.NetStandard.csproj index bc0951e..cdd7d51 100644 --- a/SystemExtensions.NetStandard/SystemExtensions.NetStandard.csproj +++ b/SystemExtensions.NetStandard/SystemExtensions.NetStandard.csproj @@ -7,7 +7,7 @@ LICENSE true System - 1.8 + 1.9 Alexandru Macocian https://github.com/AlexMacocian/SystemExtensions Extensions for the System namespace @@ -24,7 +24,7 @@ - + diff --git a/SystemExtensions.Tests/Extensions/OptionalTests.cs b/SystemExtensions.Tests/Extensions/OptionalTests.cs deleted file mode 100644 index a2aee02..0000000 --- a/SystemExtensions.Tests/Extensions/OptionalTests.cs +++ /dev/null @@ -1,110 +0,0 @@ -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace System.Extensions.Tests; - -[TestClass] -public class OptionalTests -{ - [TestMethod] - public void SomeValueShouldEqualOptional() - { - var value = string.Empty; - var optional = value.ToOptional(); - - Assert.IsTrue(optional.Equals(value)); - } - - [TestMethod] - public void OptionalFromNullShouldNotEqual() - { - object value = null; - var optional = value.ToOptional(); - - Assert.IsFalse(optional.Equals(value)); - } - - [TestMethod] - public void OptionalFromValueShouldBeSome() - { - var optional = Optional.FromValue(new object()); - - optional.DoAny( - onNone: () => throw new InvalidOperationException()); - } - - [TestMethod] - public void OptionalFromNullShouldBeNone() - { - var optional = Optional.FromValue(null); - - optional.DoAny( - onSome: _ => throw new InvalidOperationException()); - } - - [TestMethod] - public void DoShouldExecute() - { - var optional = Optional.FromValue(string.Empty); - var nullOptional = Optional.FromValue(null); - - optional.Do( - onSome: _ => { }, - onNone: () => throw new InvalidOperationException()); - - nullOptional.Do( - onSome: _ => throw new InvalidOperationException(), - onNone: () => { }); - } - - [TestMethod] - public void DoAnyShouldExecute() - { - var optional = Optional.FromValue(string.Empty); - var nullOptional = Optional.FromValue(null); - - optional.DoAny( - onNone: () => throw new InvalidOperationException()); - - nullOptional.DoAny( - onSome: _ => throw new InvalidOperationException()); - } - - [TestMethod] - public void SwitchShouldExecute() - { - var optional = Optional.FromValue(string.Empty); - var nullOptional = Optional.FromValue(null); - - var newValue = optional.Switch( - onSome: _ => string.Empty, - onNone: () => throw new InvalidOperationException()) - .ExtractValue(); - - var newNullValue = nullOptional.Switch( - onSome: _ => throw new InvalidOperationException(), - onNone: () => null) - .ExtractValue(); - - newValue.Should().Be(string.Empty); - newNullValue.Should().Be(null); - } - - [TestMethod] - public void SwitchAnyShouldExecute() - { - var optional = Optional.FromValue(string.Empty); - var nullOptional = Optional.FromValue(null); - - var newValue = optional.SwitchAny( - onSome: _ => string.Empty) - .ExtractValue(); - - var newNullValue = nullOptional.SwitchAny( - onNone: () => null) - .ExtractValue(); - - newValue.Should().Be(string.Empty); - newNullValue.Should().Be(null); - } -} diff --git a/SystemExtensions.Tests/Extensions/ResultTests.cs b/SystemExtensions.Tests/Extensions/ResultTests.cs deleted file mode 100644 index b3d68e7..0000000 --- a/SystemExtensions.Tests/Extensions/ResultTests.cs +++ /dev/null @@ -1,116 +0,0 @@ -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace System.Extensions.Tests; - -[TestClass] -public class ResultTests -{ - [TestMethod] - public void SuccessResultShouldCreateFromSuccess() - { - var success = string.Empty; - var result = Result.Success(success); - - result.DoAny( - onFailure: () => throw new InvalidOperationException()); - } - - [TestMethod] - public void FailureResultShouldCreateFromFailure() - { - var failure = new object(); - var result = Result.Failure(failure); - - result.DoAny( - onSuccess: () => throw new InvalidOperationException()); - } - - [TestMethod] - public void DoShouldExecute() - { - var success = string.Empty; - var successResult = Result.Success(success); - - var failure = new object(); - var failedResult = Result.Failure(failure); - - successResult.Do( - onSuccess: _ => { }, - onFailure: _ => throw new InvalidOperationException()); - - failedResult.Do( - onSuccess: _ => throw new InvalidOperationException(), - onFailure: _ => { }); - } - - [TestMethod] - public void DoAnyShouldExecute() - { - var success = string.Empty; - var successResult = Result.Success(success); - - var failure = new object(); - var failedResult = Result.Failure(failure); - - successResult.DoAny( - onSuccess: _ => { }); - - failedResult.DoAny( - onFailure: _ => { }); - } - - [TestMethod] - public void SwitchShouldExecute() - { - var success = string.Empty; - var successResult = Result.Success(success); - - var failure = new object(); - var failedResult = Result.Failure(failure); - - var successSwitch = successResult.Switch( - onSuccess: _ => string.Empty, - onFailure: _ => throw new InvalidOperationException()); - - var failedSwitch = failedResult.Switch( - onSuccess: _ => throw new InvalidOperationException(), - onFailure: _ => string.Empty); - - success.Should().Be(failedSwitch); - } - - [TestMethod] - public void SwitchAnyShouldExecute() - { - var success = string.Empty; - var successResult = Result.Success(success); - - var failure = new object(); - var failedResult = Result.Failure(failure); - - var successSwitch = successResult.SwitchAny( - onSuccess: _ => string.Empty); - - var failedSwitch = failedResult.SwitchAny( - onFailure: _ => string.Empty); - - success.Should().Be(failedSwitch); - } - - [TestMethod] - public void ToOptionalShouldConvert() - { - var success = string.Empty; - var successResult = Result.Success(success); - - var failure = new object(); - var failedResult = Result.Failure(failure); - - var successOptional = successResult.ToOptional(); - var failureOptional = failedResult.ToOptional(); - - successOptional.Should().NotBeNull(); - failureOptional.Should().NotBeNull(); - } -}