mirror of
https://github.com/AlexMacocian/SystemExtensions.git
synced 2026-07-24 03:56:27 +00:00
Improve IHttpClient factories (#20)
Codestyle fixes Setup CODEOWNERS Setup dependabot
This commit is contained in:
@@ -1,25 +1,24 @@
|
||||
using System.IO;
|
||||
|
||||
namespace System.Extensions
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class BytesExtensions
|
||||
{
|
||||
public static class BytesExtensions
|
||||
public static byte[] ReadAllBytes(this Stream stream)
|
||||
{
|
||||
public static byte[] ReadAllBytes(this Stream stream)
|
||||
if (stream is null)
|
||||
{
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
var buffer = new byte[256];
|
||||
using var ms = new MemoryStream();
|
||||
int read;
|
||||
while ((read = stream.Read(buffer, 0, 256)) > 0)
|
||||
{
|
||||
ms.Write(buffer, 0, read);
|
||||
}
|
||||
|
||||
return ms.ToArray();
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
var buffer = new byte[256];
|
||||
using var ms = new MemoryStream();
|
||||
int read;
|
||||
while ((read = stream.Read(buffer, 0, 256)) > 0)
|
||||
{
|
||||
ms.Write(buffer, 0, read);
|
||||
}
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,49 @@
|
||||
namespace System.Extensions
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class CastExtensions
|
||||
{
|
||||
public static class CastExtensions
|
||||
public static int Floor(this double value)
|
||||
{
|
||||
public static int Floor(this double value)
|
||||
{
|
||||
return (int)Math.Floor(value);
|
||||
}
|
||||
return (int)Math.Floor(value);
|
||||
}
|
||||
|
||||
public static int Ceiling(this double value)
|
||||
{
|
||||
return (int)Math.Ceiling(value);
|
||||
}
|
||||
public static int Ceiling(this double value)
|
||||
{
|
||||
return (int)Math.Ceiling(value);
|
||||
}
|
||||
|
||||
public static int Round(this double value)
|
||||
{
|
||||
return (int)Math.Round(value);
|
||||
}
|
||||
public static int Round(this double value)
|
||||
{
|
||||
return (int)Math.Round(value);
|
||||
}
|
||||
|
||||
public static int Floor(this float value)
|
||||
{
|
||||
return (int)Math.Floor(value);
|
||||
}
|
||||
public static int Floor(this float value)
|
||||
{
|
||||
return (int)Math.Floor(value);
|
||||
}
|
||||
|
||||
public static int Ceiling(this float value)
|
||||
{
|
||||
return (int)Math.Ceiling(value);
|
||||
}
|
||||
public static int Ceiling(this float value)
|
||||
{
|
||||
return (int)Math.Ceiling(value);
|
||||
}
|
||||
|
||||
public static int Round(this float value)
|
||||
{
|
||||
return (int)Math.Round(value);
|
||||
}
|
||||
public static int Round(this float value)
|
||||
{
|
||||
return (int)Math.Round(value);
|
||||
}
|
||||
|
||||
public static int ToInt(this double value)
|
||||
{
|
||||
return (int)value;
|
||||
}
|
||||
public static int ToInt(this double value)
|
||||
{
|
||||
return (int)value;
|
||||
}
|
||||
|
||||
public static int ToInt(this float value)
|
||||
{
|
||||
return (int)value;
|
||||
}
|
||||
public static int ToInt(this float value)
|
||||
{
|
||||
return (int)value;
|
||||
}
|
||||
|
||||
public static int ToInt(this decimal value)
|
||||
{
|
||||
return (int)value;
|
||||
}
|
||||
public static int ToInt(this decimal value)
|
||||
{
|
||||
return (int)value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,88 +1,88 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace System.Extensions
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class LinqExtensions
|
||||
{
|
||||
public static class LinqExtensions
|
||||
public static bool None<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
|
||||
{
|
||||
public static bool None<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
|
||||
{
|
||||
enumerable.ThrowIfNull(nameof(enumerable));
|
||||
predicate.ThrowIfNull(nameof(predicate));
|
||||
enumerable.ThrowIfNull(nameof(enumerable));
|
||||
predicate.ThrowIfNull(nameof(predicate));
|
||||
|
||||
return !enumerable.Any(predicate);
|
||||
return !enumerable.Any(predicate);
|
||||
}
|
||||
|
||||
public static bool None<T>(this IEnumerable<T> enumerable)
|
||||
{
|
||||
enumerable.ThrowIfNull(nameof(enumerable));
|
||||
|
||||
return !enumerable.Any();
|
||||
}
|
||||
|
||||
public static ICollection<T> ClearAnd<T>(this ICollection<T> collection)
|
||||
{
|
||||
if (collection is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
}
|
||||
|
||||
public static bool None<T>(this IEnumerable<T> enumerable)
|
||||
collection.Clear();
|
||||
return collection;
|
||||
}
|
||||
|
||||
public static ICollection<T> AddRange<T>(this ICollection<T> collection, IEnumerable<T> values)
|
||||
{
|
||||
if (collection is null)
|
||||
{
|
||||
enumerable.ThrowIfNull(nameof(enumerable));
|
||||
|
||||
return !enumerable.Any();
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
}
|
||||
|
||||
public static ICollection<T> ClearAnd<T>(this ICollection<T> collection)
|
||||
if (values is null)
|
||||
{
|
||||
if (collection is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
}
|
||||
|
||||
collection.Clear();
|
||||
return collection;
|
||||
}
|
||||
|
||||
public static ICollection<T> AddRange<T>(this ICollection<T> collection, IEnumerable<T> values)
|
||||
{
|
||||
if (collection is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
}
|
||||
|
||||
if (values is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(values));
|
||||
}
|
||||
|
||||
foreach (var item in values)
|
||||
{
|
||||
collection.Add(item);
|
||||
}
|
||||
|
||||
return collection;
|
||||
throw new ArgumentNullException(nameof(values));
|
||||
}
|
||||
|
||||
public static int IndexOfWhere<T>(this ICollection<T> collection, Func<T, bool> selector)
|
||||
foreach (var item in values)
|
||||
{
|
||||
if (collection is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
}
|
||||
|
||||
if (selector is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(selector));
|
||||
}
|
||||
|
||||
var index = 0;
|
||||
foreach (var item in collection)
|
||||
{
|
||||
if (selector(item))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
collection.Add(item);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> Do<T>(this IEnumerable<T> enumerable, Action<T> action)
|
||||
return collection;
|
||||
}
|
||||
|
||||
public static int IndexOfWhere<T>(this ICollection<T> collection, Func<T, bool> selector)
|
||||
{
|
||||
if (collection is null)
|
||||
{
|
||||
foreach(var value in enumerable)
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
}
|
||||
|
||||
if (selector is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(selector));
|
||||
}
|
||||
|
||||
var index = 0;
|
||||
foreach (var item in collection)
|
||||
{
|
||||
if (selector(item))
|
||||
{
|
||||
action(value);
|
||||
yield return value;
|
||||
return index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> Do<T>(this IEnumerable<T> enumerable, Action<T> action)
|
||||
{
|
||||
foreach(var value in enumerable)
|
||||
{
|
||||
action(value);
|
||||
yield return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Logging;
|
||||
|
||||
namespace System.Extensions
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class LoggingExtensions
|
||||
{
|
||||
public static class LoggingExtensions
|
||||
public static ScopedLogger<T> CreateScopedLogger<T>(this ILogger<T> logger, string methodName, string flowIdentifier)
|
||||
{
|
||||
public static ScopedLogger<T> CreateScopedLogger<T>(this ILogger<T> logger, string methodName, string flowIdentifier)
|
||||
{
|
||||
return ScopedLogger<T>.Create(logger, methodName, flowIdentifier);
|
||||
}
|
||||
return ScopedLogger<T>.Create(logger, methodName, flowIdentifier);
|
||||
}
|
||||
}
|
||||
@@ -1,59 +1,58 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace System.Extensions
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class ObjectExtensions
|
||||
{
|
||||
public static class ObjectExtensions
|
||||
public static T Deserialize<T>(this string serialized)
|
||||
where T : class
|
||||
{
|
||||
public static T Deserialize<T>(this string serialized)
|
||||
where T : class
|
||||
if (serialized.IsNullOrWhiteSpace())
|
||||
{
|
||||
if (serialized.IsNullOrWhiteSpace())
|
||||
{
|
||||
throw new ArgumentException("Provided serialized string cannot be null or whitespace", nameof(serialized));
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<T>(serialized);
|
||||
throw new ArgumentException("Provided serialized string cannot be null or whitespace", nameof(serialized));
|
||||
}
|
||||
|
||||
public static string Serialize<T>(this T obj)
|
||||
where T : class
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
return JsonConvert.DeserializeObject<T>(serialized);
|
||||
}
|
||||
|
||||
return JsonConvert.SerializeObject(obj);
|
||||
public static string Serialize<T>(this T obj)
|
||||
where T : class
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
public static T Cast<T>(this object obj)
|
||||
return JsonConvert.SerializeObject(obj);
|
||||
}
|
||||
|
||||
public static T Cast<T>(this object obj)
|
||||
{
|
||||
return (T)obj;
|
||||
}
|
||||
|
||||
public static T As<T>(this object obj) where T : class
|
||||
{
|
||||
return obj as T;
|
||||
}
|
||||
|
||||
public static Optional<T> ToOptional<T>(this T obj)
|
||||
{
|
||||
return Optional.FromValue(obj);
|
||||
}
|
||||
|
||||
public static T ThrowIfNull<T>([ValidatedNotNull] this T obj, string name) where T : class
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
return (T)obj;
|
||||
throw new ArgumentNullException(name);
|
||||
}
|
||||
|
||||
public static T As<T>(this object obj) where T : class
|
||||
{
|
||||
return obj as T;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static Optional<T> ToOptional<T>(this T obj)
|
||||
{
|
||||
return Optional.FromValue(obj);
|
||||
}
|
||||
|
||||
public static T ThrowIfNull<T>([ValidatedNotNull] this T obj, string name) where T : class
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(name);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
sealed class ValidatedNotNullAttribute : Attribute
|
||||
{
|
||||
}
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
sealed class ValidatedNotNullAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,192 +1,193 @@
|
||||
namespace System.Extensions
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class Optional
|
||||
{
|
||||
public static class Optional
|
||||
public static Optional<T> None<T>()
|
||||
{
|
||||
public static Optional<T> None<T>()
|
||||
return new Optional<T>.None();
|
||||
}
|
||||
|
||||
public static Optional<T> FromValue<T>(T value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return new Optional<T>.None();
|
||||
}
|
||||
|
||||
public static Optional<T> FromValue<T>(T value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return new Optional<T>.None();
|
||||
}
|
||||
return new Optional<T>.Some(value);
|
||||
}
|
||||
}
|
||||
|
||||
return new Optional<T>.Some(value);
|
||||
public abstract class Optional<T> : IEquatable<Optional<T>>
|
||||
{
|
||||
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<T> Do(Action<T> 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<T> DoAny(Action<T> onSome = null, Action onNone = null)
|
||||
{
|
||||
if (this is Some)
|
||||
{
|
||||
onSome?.Invoke(this.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
onNone?.Invoke();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
public Optional<V> Switch<V>(Func<T, V> onSome, Func<V> 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<V> SwitchAny<V>(Func<T, V> onSome = null, Func<V> 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 abstract class Optional<T> : IEquatable<Optional<T>>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
public Optional(T value)
|
||||
if (obj is Optional<T>)
|
||||
{
|
||||
this.Value = value;
|
||||
return this.Equals(obj);
|
||||
}
|
||||
|
||||
private T Value { get; }
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
public T ExtractValue()
|
||||
public bool Equals(Optional<T> other)
|
||||
{
|
||||
if (this is Some && other is Some)
|
||||
{
|
||||
if (this is None)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
return this.As<Some>().Equals(other.As<Some>());
|
||||
}
|
||||
public Optional<T> Do(Action<T> onSome, Action onNone)
|
||||
{
|
||||
if (onSome is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onSome));
|
||||
}
|
||||
|
||||
if (onNone is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onNone));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this is Some)
|
||||
{
|
||||
onSome.Invoke(this.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
onNone.Invoke();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Optional<T> DoAny(Action<T> onSome = null, Action onNone = null)
|
||||
{
|
||||
if (this is Some)
|
||||
{
|
||||
onSome?.Invoke(this.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
onNone?.Invoke();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Optional<V> Switch<V>(Func<T, V> onSome, Func<V> onNone)
|
||||
{
|
||||
if (onSome is null)
|
||||
{
|
||||
throw new ArgumentNullException($"{nameof(onSome)}");
|
||||
}
|
||||
public static implicit operator Optional<T>(T value)
|
||||
{
|
||||
return Optional.FromValue(value);
|
||||
}
|
||||
|
||||
if (onNone is null)
|
||||
{
|
||||
throw new ArgumentNullException($"{nameof(onNone)}");
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Value == null ? base.GetHashCode() : this.Value.GetHashCode();
|
||||
}
|
||||
|
||||
if (this is Some)
|
||||
{
|
||||
return Optional.FromValue(onSome.Invoke(this.Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Optional.FromValue(onNone.Invoke());
|
||||
}
|
||||
}
|
||||
public Optional<V> SwitchAny<V>(Func<T, V> onSome = null, Func<V> onNone = null)
|
||||
internal class Some : Optional<T>, IEquatable<Some>
|
||||
{
|
||||
public Some(T value) : base(value)
|
||||
{
|
||||
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<T>)
|
||||
if (obj is Some)
|
||||
{
|
||||
return this.Equals(obj);
|
||||
return this.Equals(obj.As<Some>());
|
||||
}
|
||||
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
public bool Equals(Optional<T> other)
|
||||
public bool Equals(Some other)
|
||||
{
|
||||
if (this is Some && other is Some)
|
||||
if (other is None)
|
||||
{
|
||||
return this.As<Some>().Equals(other.As<Some>());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (other is Some)
|
||||
{
|
||||
return this.Value.Equals(other.Value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static implicit operator Optional<T>(T value)
|
||||
public static bool operator ==(Some left, Some right)
|
||||
{
|
||||
return Optional.FromValue(value);
|
||||
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 == null ? base.GetHashCode() : this.Value.GetHashCode();
|
||||
return this.Value is object ? this.Value.GetHashCode() : this.As<object>().GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
internal class Some : Optional<T>, IEquatable<Some>
|
||||
internal class None : Optional<T>
|
||||
{
|
||||
public None() : base(default)
|
||||
{
|
||||
public Some(T value) : base(value)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is Some)
|
||||
{
|
||||
return this.Equals(obj.As<Some>());
|
||||
}
|
||||
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
public bool Equals(Some other)
|
||||
{
|
||||
if (other is None)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (other is Some)
|
||||
{
|
||||
return 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<object>().GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
internal class None : Optional<T>
|
||||
{
|
||||
public None() : base(default)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,209 +1,216 @@
|
||||
namespace System.Extensions
|
||||
namespace System.Extensions;
|
||||
|
||||
public class Result<TSuccess, TFailure>
|
||||
{
|
||||
public class Result<TSuccess, TFailure>
|
||||
private readonly object value;
|
||||
|
||||
public Result(TSuccess successValue)
|
||||
{
|
||||
private readonly object value;
|
||||
this.value = successValue;
|
||||
}
|
||||
public Result(TFailure failureValue)
|
||||
{
|
||||
this.value = failureValue;
|
||||
}
|
||||
|
||||
public Result(TSuccess successValue)
|
||||
{
|
||||
value = successValue;
|
||||
}
|
||||
public Result(TFailure failureValue)
|
||||
{
|
||||
value = failureValue;
|
||||
}
|
||||
public bool TryExtractSuccess(out TSuccess successValue)
|
||||
{
|
||||
|
||||
public bool TryExtractSuccess(out TSuccess successValue)
|
||||
if (this.value is TSuccess success)
|
||||
{
|
||||
|
||||
if (value is TSuccess success)
|
||||
{
|
||||
successValue = success;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
successValue = default;
|
||||
return false;
|
||||
}
|
||||
successValue = success;
|
||||
return true;
|
||||
}
|
||||
public bool TryExtractFailure(out TFailure failureValue)
|
||||
else
|
||||
{
|
||||
|
||||
if (value is TFailure failure)
|
||||
{
|
||||
failureValue = failure;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
failureValue = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public Result<TSuccess, TFailure> Do(Action onSuccess, Action onFailure)
|
||||
{
|
||||
if (onSuccess is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onSuccess));
|
||||
}
|
||||
|
||||
if (onFailure is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onFailure));
|
||||
}
|
||||
|
||||
if (value is TSuccess)
|
||||
{
|
||||
onSuccess.Invoke();
|
||||
}
|
||||
else if (value is TFailure)
|
||||
{
|
||||
onFailure.Invoke();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Result<TSuccess, TFailure> DoAny(Action onSuccess = null, Action onFailure = null)
|
||||
{
|
||||
if (value is TSuccess)
|
||||
{
|
||||
onSuccess?.Invoke();
|
||||
}
|
||||
else if (value is TFailure)
|
||||
{
|
||||
onFailure?.Invoke();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Result<TSuccess, TFailure> Do(Action<TSuccess> onSuccess, Action<TFailure> onFailure)
|
||||
{
|
||||
if (onSuccess is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onSuccess));
|
||||
}
|
||||
|
||||
if (onFailure is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onFailure));
|
||||
}
|
||||
|
||||
if (value is TSuccess success)
|
||||
{
|
||||
onSuccess.Invoke(success);
|
||||
}
|
||||
else if (value is TFailure failure)
|
||||
{
|
||||
onFailure.Invoke(failure);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Result<TSuccess, TFailure> DoAny(Action<TSuccess> onSuccess = null, Action<TFailure> onFailure = null)
|
||||
{
|
||||
if (value is TSuccess success)
|
||||
{
|
||||
onSuccess?.Invoke(success);
|
||||
}
|
||||
else if (value is TFailure failure)
|
||||
{
|
||||
onFailure?.Invoke(failure);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public T Switch<T>(Func<TSuccess, T> onSuccess, Func<TFailure, T> onFailure)
|
||||
{
|
||||
if (onSuccess is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onSuccess));
|
||||
}
|
||||
|
||||
if (onFailure is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onFailure));
|
||||
}
|
||||
|
||||
if (value is TSuccess success)
|
||||
{
|
||||
return onSuccess.Invoke(success);
|
||||
}
|
||||
else if (value is TFailure failure)
|
||||
{
|
||||
return onFailure.Invoke(failure);
|
||||
}
|
||||
throw new InvalidOperationException($"{nameof(value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to {typeof(T)}");
|
||||
}
|
||||
public T SwitchAny<T>(Func<TSuccess, T> onSuccess = null, Func<TFailure, T> onFailure = null)
|
||||
{
|
||||
if (value is TSuccess success)
|
||||
{
|
||||
return onSuccess is null ? default : onSuccess.Invoke(success);
|
||||
}
|
||||
else if (value is TFailure failure)
|
||||
{
|
||||
return onFailure is null ? default : onFailure.Invoke(failure);
|
||||
}
|
||||
throw new InvalidOperationException($"{nameof(value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to {typeof(T)}");
|
||||
}
|
||||
public Result<V, K> Switch<V, K>(Func<TSuccess, V> onSuccess, Func<TFailure, K> onFailure)
|
||||
{
|
||||
if (onSuccess is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onSuccess));
|
||||
}
|
||||
|
||||
if (onFailure is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(onFailure));
|
||||
}
|
||||
|
||||
if (value is TSuccess success)
|
||||
{
|
||||
return Result<V, K>.Success(onSuccess.Invoke(success));
|
||||
}
|
||||
else if (value is TFailure failure)
|
||||
{
|
||||
return Result<V, K>.Failure(onFailure.Invoke(failure));
|
||||
}
|
||||
throw new InvalidOperationException($"{nameof(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<V, K> SwitchAny<V, K>(Func<TSuccess, V> onSuccess, Func<TFailure, K> onFailure)
|
||||
{
|
||||
if (value is TSuccess success)
|
||||
{
|
||||
return Result<V, K>.Success(onSuccess is null ? default : onSuccess.Invoke(success));
|
||||
}
|
||||
else if (value is TFailure failure)
|
||||
{
|
||||
return Result<V, K>.Failure(onFailure is null ? default : onFailure.Invoke(failure));
|
||||
}
|
||||
throw new InvalidOperationException($"{nameof(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<TSuccess> ToOptional()
|
||||
{
|
||||
if (value is TSuccess)
|
||||
{
|
||||
return Optional.FromValue(value.Cast<TSuccess>());
|
||||
}
|
||||
|
||||
return Optional.None<TSuccess>();
|
||||
}
|
||||
|
||||
public static implicit operator Result<TSuccess, TFailure>(TSuccess success)
|
||||
{
|
||||
return Success(success);
|
||||
}
|
||||
|
||||
public static implicit operator Result<TSuccess, TFailure>(TFailure failure)
|
||||
{
|
||||
return Failure(failure);
|
||||
}
|
||||
|
||||
public static Result<TSuccess, TFailure> Success(TSuccess value)
|
||||
{
|
||||
return new Result<TSuccess, TFailure>(value);
|
||||
}
|
||||
public static Result<TSuccess, TFailure> Failure(TFailure value)
|
||||
{
|
||||
return new Result<TSuccess, TFailure>(value);
|
||||
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<TSuccess, TFailure> 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<TSuccess, TFailure> 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<TSuccess, TFailure> Do(Action<TSuccess> onSuccess, Action<TFailure> 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<TSuccess, TFailure> DoAny(Action<TSuccess> onSuccess = null, Action<TFailure> 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<T>(Func<TSuccess, T> onSuccess, Func<TFailure, T> 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<T>(Func<TSuccess, T> onSuccess = null, Func<TFailure, T> 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<V, K> Switch<V, K>(Func<TSuccess, V> onSuccess, Func<TFailure, K> 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<V, K>.Success(onSuccess.Invoke(success));
|
||||
}
|
||||
else if (this.value is TFailure failure)
|
||||
{
|
||||
return Result<V, K>.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<V, K> SwitchAny<V, K>(Func<TSuccess, V> onSuccess, Func<TFailure, K> onFailure)
|
||||
{
|
||||
if (this.value is TSuccess success)
|
||||
{
|
||||
return Result<V, K>.Success(onSuccess is null ? default : onSuccess.Invoke(success));
|
||||
}
|
||||
else if (this.value is TFailure failure)
|
||||
{
|
||||
return Result<V, K>.Failure(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 Result of type {typeof(V)} or {typeof(K)}");
|
||||
}
|
||||
public Optional<TSuccess> ToOptional()
|
||||
{
|
||||
if (this.value is TSuccess)
|
||||
{
|
||||
return Optional.FromValue(this.value.Cast<TSuccess>());
|
||||
}
|
||||
|
||||
return Optional.None<TSuccess>();
|
||||
}
|
||||
|
||||
public static implicit operator Result<TSuccess, TFailure>(TSuccess success)
|
||||
{
|
||||
return Success(success);
|
||||
}
|
||||
|
||||
public static implicit operator Result<TSuccess, TFailure>(TFailure failure)
|
||||
{
|
||||
return Failure(failure);
|
||||
}
|
||||
|
||||
public static Result<TSuccess, TFailure> Success(TSuccess value)
|
||||
{
|
||||
return new Result<TSuccess, TFailure>(value);
|
||||
}
|
||||
public static Result<TSuccess, TFailure> Failure(TFailure value)
|
||||
{
|
||||
return new Result<TSuccess, TFailure>(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,85 +1,84 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Extensions
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class StreamExtensions
|
||||
{
|
||||
public static class StreamExtensions
|
||||
public static void DoWhileReading(this Stream stream, Action<int, byte[]> action, int bufferLength = 256)
|
||||
{
|
||||
public static void DoWhileReading(this Stream stream, Action<int, byte[]> action, int bufferLength = 256)
|
||||
if (stream is null)
|
||||
{
|
||||
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);
|
||||
}
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
public static byte[] ReadBytes(this Stream stream, int count)
|
||||
if (action is null)
|
||||
{
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
var buffer = new byte[count];
|
||||
stream.Read(buffer, 0, count);
|
||||
return buffer;
|
||||
throw new ArgumentNullException(nameof(action));
|
||||
}
|
||||
|
||||
public static Stream Rewind(this Stream stream)
|
||||
var buffer = new byte[bufferLength];
|
||||
var read = stream.Read(buffer, 0, bufferLength);
|
||||
while(read > 0)
|
||||
{
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
if (!stream.CanSeek)
|
||||
{
|
||||
throw new InvalidOperationException("Stream doesn't support rewinding");
|
||||
}
|
||||
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return stream;
|
||||
}
|
||||
|
||||
public static string ReadUntil(this StreamReader sr, string delim)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var found = false;
|
||||
|
||||
while (!found && !sr.EndOfStream)
|
||||
{
|
||||
for (var i = 0; i < delim.Length; i++)
|
||||
{
|
||||
var c = (char)sr.Read();
|
||||
sb.Append(c);
|
||||
|
||||
if (c != delim[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == delim.Length - 1)
|
||||
{
|
||||
sb.Remove(sb.Length - delim.Length, delim.Length);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
action(bufferLength, buffer);
|
||||
read = stream.Read(buffer, 0, bufferLength);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] ReadBytes(this Stream stream, int count)
|
||||
{
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
var buffer = new byte[count];
|
||||
stream.Read(buffer, 0, count);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static Stream Rewind(this Stream stream)
|
||||
{
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
if (!stream.CanSeek)
|
||||
{
|
||||
throw new InvalidOperationException("Stream doesn't support rewinding");
|
||||
}
|
||||
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return stream;
|
||||
}
|
||||
|
||||
public static string ReadUntil(this StreamReader sr, string delim)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var found = false;
|
||||
|
||||
while (!found && !sr.EndOfStream)
|
||||
{
|
||||
for (var i = 0; i < delim.Length; i++)
|
||||
{
|
||||
var c = (char)sr.Read();
|
||||
sb.Append(c);
|
||||
|
||||
if (c != delim[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == delim.Length - 1)
|
||||
{
|
||||
sb.Remove(sb.Length - delim.Length, delim.Length);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
using System.Text;
|
||||
|
||||
namespace System.Extensions
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class StringExtensions
|
||||
{
|
||||
public static class StringExtensions
|
||||
public static bool IsNullOrEmpty(this string s)
|
||||
{
|
||||
public static bool IsNullOrEmpty(this string s)
|
||||
{
|
||||
return string.IsNullOrEmpty(s);
|
||||
}
|
||||
return string.IsNullOrEmpty(s);
|
||||
}
|
||||
|
||||
public static bool IsNullOrWhiteSpace(this string s)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(s);
|
||||
}
|
||||
public static bool IsNullOrWhiteSpace(this string s)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(s);
|
||||
}
|
||||
|
||||
public static byte[] GetBytes(this string s)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(s);
|
||||
}
|
||||
public static byte[] GetBytes(this string s)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(s);
|
||||
}
|
||||
|
||||
public static string GetString(this byte[] bytes)
|
||||
{
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
public static string GetString(this byte[] bytes)
|
||||
{
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,183 +2,184 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Extensions
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class TaskExtensions
|
||||
{
|
||||
public static class TaskExtensions
|
||||
/// <summary>
|
||||
/// Mark task as <see cref="TaskCreationOptions.LongRunning"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Result type.</typeparam>
|
||||
/// <param name="task">Task.</param>
|
||||
/// <returns>The started <see cref="Task{TResult}"/></returns>
|
||||
public static Task<T> LongRunning<T>(this Task<T> task)
|
||||
{
|
||||
/// <summary>
|
||||
/// Mark task as <see cref="TaskCreationOptions.LongRunning"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Result type.</typeparam>
|
||||
/// <param name="task">Task.</param>
|
||||
/// <returns>The started <see cref="Task{TResult}"/></returns>
|
||||
public static Task<T> LongRunning<T>(this Task<T> task)
|
||||
return Task.Factory.StartNew(async () =>
|
||||
{
|
||||
return Task.Factory.StartNew(async () =>
|
||||
{
|
||||
return await task;
|
||||
}, TaskCreationOptions.LongRunning).Unwrap();
|
||||
return await task;
|
||||
}, TaskCreationOptions.LongRunning).Unwrap();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mark task as <see cref="TaskCreationOptions.LongRunning"/>.
|
||||
/// </summary>
|
||||
/// <param name="task">Task.</param>
|
||||
/// <returns>The started <see cref="Task"/></returns>
|
||||
public static Task LongRunning(this Task task)
|
||||
{
|
||||
return Task.Factory.StartNew(async () =>
|
||||
{
|
||||
await task;
|
||||
}, TaskCreationOptions.LongRunning).Unwrap();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute action periodically and asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="onTick">Action to be executed.</param>
|
||||
/// <param name="dueTime">Time to pass before starting to execute.</param>
|
||||
/// <param name="interval">Interval between procs.</param>
|
||||
/// <param name="token">Cancellation token used to cancel the cycle.</param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mark task as <see cref="TaskCreationOptions.LongRunning"/>.
|
||||
/// </summary>
|
||||
/// <param name="task">Task.</param>
|
||||
/// <returns>The started <see cref="Task"/></returns>
|
||||
public static Task LongRunning(this Task task)
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
return Task.Factory.StartNew(async () =>
|
||||
onTick?.Invoke();
|
||||
if (interval > TimeSpan.Zero)
|
||||
{
|
||||
await task;
|
||||
}, TaskCreationOptions.LongRunning).Unwrap();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute action periodically and asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="onTick">Action to be executed.</param>
|
||||
/// <param name="dueTime">Time to pass before starting to execute.</param>
|
||||
/// <param name="interval">Interval between procs.</param>
|
||||
/// <param name="token">Cancellation token used to cancel the cycle.</param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute's an async Task<T> method which has a void return value synchronously
|
||||
/// </summary>
|
||||
/// <param name="task">Task<T> method to execute</param>
|
||||
public static void RunSync(this Func<Task> 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();
|
||||
}
|
||||
}, null);
|
||||
synch.BeginMessageLoop();
|
||||
|
||||
SynchronizationContext.SetSynchronizationContext(oldContext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute's an async Task<T> method which has a T return type synchronously
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Return Type</typeparam>
|
||||
/// <param name="task">Task<T> method to execute</param>
|
||||
/// <returns></returns>
|
||||
public static T RunSync<T>(this Func<Task<T>> 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();
|
||||
}
|
||||
}, null);
|
||||
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<Tuple<SendOrPostCallback, object>> items =
|
||||
new Queue<Tuple<SendOrPostCallback, object>>();
|
||||
|
||||
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 (items)
|
||||
{
|
||||
items.Enqueue(Tuple.Create(d, state));
|
||||
}
|
||||
workItemsWaiting.Set();
|
||||
}
|
||||
|
||||
public void EndMessageLoop()
|
||||
{
|
||||
Post(_ => done = true, null);
|
||||
}
|
||||
|
||||
public void BeginMessageLoop()
|
||||
{
|
||||
while (!done)
|
||||
{
|
||||
Tuple<SendOrPostCallback, object> task = null;
|
||||
lock (items)
|
||||
{
|
||||
if (items.Count > 0)
|
||||
{
|
||||
task = items.Dequeue();
|
||||
}
|
||||
}
|
||||
if (task != null)
|
||||
{
|
||||
task.Item1(task.Item2);
|
||||
if (InnerException != null) // the method threw an exeption
|
||||
{
|
||||
throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
workItemsWaiting.WaitOne();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override SynchronizationContext CreateCopy()
|
||||
{
|
||||
return this;
|
||||
await Task.Delay(interval, token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute's an async Task<T> method which has a void return value synchronously
|
||||
/// </summary>
|
||||
/// <param name="task">Task<T> method to execute</param>
|
||||
public static void RunSync(this Func<Task> 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();
|
||||
}
|
||||
}, null);
|
||||
synch.BeginMessageLoop();
|
||||
|
||||
SynchronizationContext.SetSynchronizationContext(oldContext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute's an async Task<T> method which has a T return type synchronously
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Return Type</typeparam>
|
||||
/// <param name="task">Task<T> method to execute</param>
|
||||
/// <returns></returns>
|
||||
public static T RunSync<T>(this Func<Task<T>> 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();
|
||||
}
|
||||
}, null);
|
||||
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<Tuple<SendOrPostCallback, object>> items =
|
||||
new Queue<Tuple<SendOrPostCallback, object>>();
|
||||
|
||||
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, null);
|
||||
}
|
||||
|
||||
public void BeginMessageLoop()
|
||||
{
|
||||
while (!this.done)
|
||||
{
|
||||
Tuple<SendOrPostCallback, object> task = null;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,72 +1,73 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Extensions
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class Try
|
||||
{
|
||||
public static class Try
|
||||
public static Try<TResult> Action<TResult>(Func<TResult> act)
|
||||
{
|
||||
public static Try<TResult> Action<TResult>(Func<TResult> act)
|
||||
return new Try<TResult>(act);
|
||||
}
|
||||
}
|
||||
public class Try<TResult>
|
||||
{
|
||||
private readonly Func<TResult> action;
|
||||
private readonly List<Func<Exception, TResult>> catchActions = new List<Func<Exception, TResult>>();
|
||||
internal Try(Func<TResult> action)
|
||||
{
|
||||
this.action = action;
|
||||
}
|
||||
public static Try<TResult> Action(Func<TResult> act)
|
||||
{
|
||||
return new Try<TResult>(act);
|
||||
}
|
||||
|
||||
public Try<TResult> Catch<TException>(Func<TException, TResult> act) where TException : Exception
|
||||
{
|
||||
this.catchActions.Add((Func<Exception, TResult>)act);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TResult Run()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Try<TResult>(act);
|
||||
return this.action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
foreach (var catchAction in this.catchActions)
|
||||
{
|
||||
return catchAction(ex);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public class Try<TResult>
|
||||
|
||||
public TResult Finally(Action act)
|
||||
{
|
||||
private readonly Func<TResult> action;
|
||||
private readonly List<Func<Exception, TResult>> catchActions = new List<Func<Exception, TResult>>();
|
||||
internal Try(Func<TResult> action)
|
||||
if (act is null)
|
||||
{
|
||||
this.action = action;
|
||||
}
|
||||
public static Try<TResult> Action(Func<TResult> act)
|
||||
{
|
||||
return new Try<TResult>(act);
|
||||
throw new ArgumentNullException(nameof(act));
|
||||
}
|
||||
|
||||
public Try<TResult> Catch<TException>(Func<TException, TResult> act) where TException : Exception
|
||||
try
|
||||
{
|
||||
this.catchActions.Add((Func<Exception, TResult>)act);
|
||||
return this;
|
||||
return this.action();
|
||||
}
|
||||
|
||||
public TResult Run()
|
||||
catch (Exception ex)
|
||||
{
|
||||
try
|
||||
foreach (var catchAction in this.catchActions)
|
||||
{
|
||||
return action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
foreach (var catchAction in this.catchActions)
|
||||
{
|
||||
return catchAction(ex);
|
||||
}
|
||||
throw;
|
||||
return catchAction(ex);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
public TResult Finally(Action act)
|
||||
finally
|
||||
{
|
||||
if (act is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(act));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return this.action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
foreach (var catchAction in this.catchActions)
|
||||
{
|
||||
return catchAction(ex);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
act();
|
||||
}
|
||||
act();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user