Skip to content

Commit

Permalink
Extend CastHelper to utilise explicit conversion methods if they exist (
Browse files Browse the repository at this point in the history
  • Loading branch information
thomhurst authored Mar 8, 2025
1 parent 19259cc commit 9279c14
Showing 1 changed file with 24 additions and 9 deletions.
33 changes: 24 additions & 9 deletions TUnit.Core/Helpers/CastHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,33 @@ public static class CastHelper
return (T?) Enum.ToObject(typeof(T), value);
}

return (T?) GetImplicitConversion(value.GetType(), typeof(T)).Invoke(null, [value]);
var conversionMethod = GetConversionMethod(value.GetType(), typeof(T));

if (conversionMethod is null)
{
return (T?) Convert.ChangeType(value, typeof(T));
}

return (T?) conversionMethod.Invoke(null, [value]);
}

private static MethodInfo GetImplicitConversion([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type baseType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type targetType)
private static MethodInfo? GetConversionMethod([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type baseType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type targetType)
{
return baseType.GetMethods(BindingFlags.Public | BindingFlags.Static)
var methods = baseType.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Concat(targetType.GetMethods(BindingFlags.Public | BindingFlags.Static))
.Where(mi => mi.Name == "op_Implicit" && mi.ReturnType == targetType)
.FirstOrDefault(mi =>
{
var pi = mi.GetParameters().FirstOrDefault();
return pi != null && pi.ParameterType == baseType;
}) ?? throw new ArgumentException($"Cannot convert from {baseType} to {targetType}");
.ToArray();

return methods
.FirstOrDefault(mi =>
mi.Name == "op_Implicit" && mi.ReturnType == targetType && HasCorrectInputType(baseType, mi))
?? methods
.FirstOrDefault(mi =>
mi.Name == "op_Explicit" && mi.ReturnType == targetType && HasCorrectInputType(baseType, mi));
}

private static bool HasCorrectInputType(Type baseType, MethodInfo mi)
{
var pi = mi.GetParameters().FirstOrDefault();
return pi != null && pi.ParameterType == baseType;
}
}

0 comments on commit 9279c14

Please sign in to comment.