2023-10-02 13:36:50 +00:00
|
|
|
using System.Collections.Concurrent;
|
2023-02-16 12:57:06 +00:00
|
|
|
using System.Diagnostics;
|
2023-06-13 11:04:07 +00:00
|
|
|
using System.Globalization;
|
2023-02-16 12:57:06 +00:00
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
using static System.Runtime.CompilerServices.MethodImplOptions;
|
|
|
|
|
|
|
|
namespace InnovEnergy.Lib.Utils;
|
|
|
|
|
2023-09-14 12:24:06 +00:00
|
|
|
|
2023-02-16 12:57:06 +00:00
|
|
|
public static class Utils
|
|
|
|
{
|
2023-09-14 12:24:06 +00:00
|
|
|
|
2023-02-16 12:57:06 +00:00
|
|
|
|
|
|
|
public static IEnumerable<String> GetEnumStrings<T>(this T e) where T : Enum
|
|
|
|
{
|
|
|
|
return GetEnumValues<T>().Select(v => v.ToString());
|
|
|
|
}
|
|
|
|
|
|
|
|
public static IReadOnlyList<TEnum> GetEnumValues<TEnum>() where TEnum : Enum
|
|
|
|
{
|
|
|
|
return (TEnum[]) Enum.GetValues(typeof(TEnum));
|
|
|
|
}
|
|
|
|
|
|
|
|
[DebuggerStepThrough][MethodImpl(AggressiveInlining)]
|
2023-06-13 11:04:07 +00:00
|
|
|
public static T ConvertTo<T>(this IConvertible convertible) where T : IConvertible
|
2023-02-16 12:57:06 +00:00
|
|
|
{
|
2023-06-13 11:04:07 +00:00
|
|
|
return (T)ConvertTo(convertible, typeof(T));
|
|
|
|
}
|
2023-02-16 12:57:06 +00:00
|
|
|
|
2023-06-13 11:04:07 +00:00
|
|
|
[DebuggerStepThrough][MethodImpl(AggressiveInlining)]
|
|
|
|
public static Object ConvertTo(this IConvertible convertible, Type type)
|
|
|
|
{
|
|
|
|
var t = type.IsEnum
|
|
|
|
? Enum.GetUnderlyingType(type)
|
|
|
|
: type;
|
2023-02-16 12:57:06 +00:00
|
|
|
|
2023-06-13 11:04:07 +00:00
|
|
|
return Convert.ChangeType(convertible, t, CultureInfo.InvariantCulture);
|
2023-02-16 12:57:06 +00:00
|
|
|
}
|
|
|
|
|
2023-03-21 12:46:15 +00:00
|
|
|
public static T Do<T>(this T t, Action action)
|
|
|
|
{
|
|
|
|
action();
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-02-16 12:57:06 +00:00
|
|
|
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
|
|
|
|
public static void Nop<T>(T _) {}
|
|
|
|
|
|
|
|
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
|
|
|
|
public static T Id<T>(T t) => t;
|
|
|
|
|
|
|
|
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
|
|
|
|
public static T CastTo<T>(this Object source) => (T) source;
|
|
|
|
|
|
|
|
|
|
|
|
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
|
|
|
|
public static T Apply<T>(this T t, Action<T> f)
|
|
|
|
{
|
|
|
|
f(t);
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
2023-08-18 13:57:00 +00:00
|
|
|
// Below does not work ;(
|
|
|
|
// [DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
|
|
|
|
// public static R Apply<T, S, R>(this T t, Func<S, R> f) where T : S
|
|
|
|
// {
|
|
|
|
// return f(t);
|
|
|
|
// }
|
|
|
|
|
2023-02-16 12:57:06 +00:00
|
|
|
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
|
|
|
|
public static R Apply<T, R>(this T t, Func<T, R> f) => f(t);
|
2023-06-13 11:04:07 +00:00
|
|
|
|
2023-03-16 13:13:39 +00:00
|
|
|
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
|
2023-02-16 12:57:06 +00:00
|
|
|
public static R Apply<T1, T2, R>(this (T1 p1, T2 p2) t, Func<T1, T2, R> f) => f(t.p1, t.p2);
|
2023-03-16 13:13:39 +00:00
|
|
|
|
|
|
|
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
|
|
|
|
public static R Apply<T1, T2, T3, R>(this (T1 p1, T2 p2, T3 p3) t, Func<T1, T2, T3, R> f) => f(t.p1, t.p2, t.p3);
|
2023-02-16 12:57:06 +00:00
|
|
|
|
|
|
|
[DebuggerStepThrough][MethodImpl(AggressiveInlining | AggressiveOptimization)]
|
|
|
|
public static R ApplyOrDefault<T, R>(this T t, Func<T, R> f, R @default)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return f(t);
|
|
|
|
}
|
|
|
|
catch
|
|
|
|
{
|
|
|
|
return @default;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Int32 Modulo(this Int32 index, Int32 length)
|
|
|
|
{
|
|
|
|
var res = index % length;
|
|
|
|
|
|
|
|
return res >= 0
|
2023-02-25 15:16:12 +00:00
|
|
|
? res
|
|
|
|
: res + length;
|
2023-02-16 12:57:06 +00:00
|
|
|
}
|
2023-03-16 13:13:39 +00:00
|
|
|
|
2023-02-26 09:38:28 +00:00
|
|
|
public static Decimal Modulo(this Decimal dividend, Decimal divisor)
|
|
|
|
{
|
|
|
|
var res = dividend % divisor;
|
|
|
|
|
|
|
|
return res >= 0
|
|
|
|
? res
|
|
|
|
: res + divisor;
|
|
|
|
}
|
2023-02-16 12:57:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
public static Int32 Clamp(this Int32 value, Int32 minValue, Int32 maxValue)
|
|
|
|
{
|
2023-06-20 13:27:53 +00:00
|
|
|
if (minValue > maxValue)
|
|
|
|
throw new ArgumentException();
|
|
|
|
|
2023-02-16 12:57:06 +00:00
|
|
|
var clamped = Math.Min(maxValue, value);
|
|
|
|
clamped = Math.Max(minValue, clamped);
|
2023-03-16 13:13:39 +00:00
|
|
|
|
2023-02-16 12:57:06 +00:00
|
|
|
return clamped;
|
|
|
|
}
|
2023-03-16 13:13:39 +00:00
|
|
|
|
2023-02-16 12:57:06 +00:00
|
|
|
public static Double Clamp(this Double value, Double minValue, Double maxValue)
|
|
|
|
{
|
2023-06-20 13:27:53 +00:00
|
|
|
if (minValue > maxValue)
|
|
|
|
throw new ArgumentException();
|
|
|
|
|
2023-02-16 12:57:06 +00:00
|
|
|
var clamped = Math.Min(maxValue, value);
|
|
|
|
clamped = Math.Max(minValue, clamped);
|
2023-06-20 13:27:53 +00:00
|
|
|
|
2023-02-16 12:57:06 +00:00
|
|
|
return clamped;
|
|
|
|
}
|
2023-03-16 13:13:39 +00:00
|
|
|
|
2023-06-20 13:34:04 +00:00
|
|
|
public static Double ClampMax(this Double value, Double maxValue)
|
|
|
|
{
|
|
|
|
return Math.Min(maxValue, value);
|
|
|
|
}
|
2023-03-16 13:13:39 +00:00
|
|
|
|
2023-06-20 13:34:04 +00:00
|
|
|
public static Double ClampMin(this Double value, Double minValue)
|
|
|
|
{
|
|
|
|
return Math.Max(minValue, value);
|
|
|
|
}
|
|
|
|
|
2023-02-16 12:57:06 +00:00
|
|
|
public static Decimal Clamp(this Decimal value, Decimal minValue, Decimal maxValue)
|
|
|
|
{
|
|
|
|
var clamped = Math.Min(maxValue, value);
|
|
|
|
clamped = Math.Max(minValue, clamped);
|
|
|
|
|
2023-03-16 13:13:39 +00:00
|
|
|
return clamped;
|
2023-02-16 12:57:06 +00:00
|
|
|
}
|
|
|
|
|
2023-03-16 13:13:39 +00:00
|
|
|
public static R ValueOrDefault<T, R>(this Dictionary<T, R> dict, T key, R defaultValue) where T : notnull
|
2023-02-16 12:57:06 +00:00
|
|
|
{
|
|
|
|
return dict.TryGetValue(key, out var value)
|
2023-03-16 13:13:39 +00:00
|
|
|
? value
|
|
|
|
: defaultValue;
|
2023-02-16 12:57:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static void CopyFilesRecursively(String source, String target)
|
|
|
|
{
|
|
|
|
CopyFilesRecursively(new DirectoryInfo(source), new DirectoryInfo(target));
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
|
|
|
|
{
|
|
|
|
foreach (var file in source.GetFiles())
|
|
|
|
file.CopyTo(Path.Combine(target.FullName, file.Name));
|
|
|
|
|
|
|
|
foreach (var dir in source.GetDirectories())
|
|
|
|
CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String ExecutingProcessName => Process.GetCurrentProcess().ProcessName;
|
2023-10-02 13:36:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
public static Func<A, R> Memoize<A, R>(Func<A, R> func) where A : notnull
|
|
|
|
{
|
|
|
|
var cache = new ConcurrentDictionary<A, R>();
|
|
|
|
|
|
|
|
return arg => cache.GetOrAdd(arg, func);
|
|
|
|
}
|
2023-02-16 12:57:06 +00:00
|
|
|
}
|