Files
Just.Railway/Railway/ReflectionHelper.cs
T
just 04c682d6fd
.NET Test / .NET tests (push) Successful in 2m53s
fixes and adjustments
2026-07-16 19:00:05 +04:00

60 lines
2.6 KiB
C#

using System.Reflection;
namespace Just.Railway;
internal static class ReflectionHelper
{
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
public static R ObjectCast<R>(object value) where R: class => (R)value;
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsEqual<T>(T? left, T? right) => TypeReflectionCache<T>.IsEqualFunc(left, right);
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <summary>
/// Test for potential nullability
/// </summary>
/// <returns>true if T is reference type or Nullable value type.</returns>
public static bool IsNullable<T>() => TypeReflectionCache<T>.IsNullable;
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsNullableStruct<T>() => TypeReflectionCache<T>.IsNullableStruct;
private static class TypeReflectionCache<T>
{
public static readonly Func<T?, T?, bool> IsEqualFunc;
static TypeReflectionCache()
{
var type = typeof(T);
var isNullableStruct = type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
var underlyingType = isNullableStruct ? type.GenericTypeArguments.First() : type;
var thisType = typeof(TypeReflectionCache<T>);
var equatableType = typeof(IEquatable<>).MakeGenericType(underlyingType);
if (equatableType.IsAssignableFrom(underlyingType))
{
var isEqualFunc = thisType.GetMethod(isNullableStruct ? nameof(IsEqualNullable) : nameof(IsEqual), BindingFlags.Static | BindingFlags.Public)
!.MakeGenericMethod(underlyingType);
IsEqualFunc = (Func<T?, T?, bool>)Delegate.CreateDelegate(typeof(Func<T?, T?, bool>), isEqualFunc);
}
else
{
IsEqualFunc = static (left, right) => left is null ? right is null : left.Equals(right);
}
IsNullableStruct = isNullableStruct;
IsNullable = isNullableStruct || !type.IsValueType;
}
public static bool IsNullable { get; }
public static bool IsNullableStruct { get; }
#pragma warning disable CS8604 // Possible null reference argument.
[Pure] public static bool IsEqual<R>(R? left, R? right) where R : notnull, IEquatable<R>, T => left is null ? right is null : left.Equals(right);
[Pure] public static bool IsEqualNullable<R>(R? left, R? right) where R : struct, IEquatable<R> => left is null ? right is null : right is not null && left.Value.Equals(right.Value);
#pragma warning restore CS8604 // Possible null reference argument.
}
}