in src/Elastic.Apm/Libraries/Newtonsoft.Json/Utilities/ConvertUtils.cs [403:552]
private static ConvertResult TryConvertInternal(object? initialValue, CultureInfo culture, Type targetType, out object? value)
{
if (initialValue == null) throw new ArgumentNullException(nameof(initialValue));
if (ReflectionUtils.IsNullableType(targetType)) targetType = Nullable.GetUnderlyingType(targetType);
var initialType = initialValue.GetType();
if (targetType == initialType)
{
value = initialValue;
return ConvertResult.Success;
}
// use Convert.ChangeType if both types are IConvertible
if (IsConvertible(initialValue.GetType()) && IsConvertible(targetType))
{
if (targetType.IsEnum())
{
if (initialValue is string)
{
value = Enum.Parse(targetType, initialValue.ToString(), true);
return ConvertResult.Success;
}
if (IsInteger(initialValue))
{
value = Enum.ToObject(targetType, initialValue);
return ConvertResult.Success;
}
}
value = System.Convert.ChangeType(initialValue, targetType, culture);
return ConvertResult.Success;
}
#if HAVE_DATE_TIME_OFFSET
if (initialValue is DateTime dt && targetType == typeof(DateTimeOffset))
{
value = new DateTimeOffset(dt);
return ConvertResult.Success;
}
#endif
if (initialValue is byte[] bytes && targetType == typeof(Guid))
{
value = new Guid(bytes);
return ConvertResult.Success;
}
if (initialValue is Guid guid && targetType == typeof(byte[]))
{
value = guid.ToByteArray();
return ConvertResult.Success;
}
if (initialValue is string s)
{
if (targetType == typeof(Guid))
{
value = new Guid(s);
return ConvertResult.Success;
}
if (targetType == typeof(Uri))
{
value = new Uri(s, UriKind.RelativeOrAbsolute);
return ConvertResult.Success;
}
if (targetType == typeof(TimeSpan))
{
value = ParseTimeSpan(s);
return ConvertResult.Success;
}
if (targetType == typeof(byte[]))
{
value = System.Convert.FromBase64String(s);
return ConvertResult.Success;
}
if (targetType == typeof(Version))
{
if (VersionTryParse(s, out var result))
{
value = result;
return ConvertResult.Success;
}
value = null;
return ConvertResult.NoValidConversion;
}
if (typeof(Type).IsAssignableFrom(targetType))
{
value = Type.GetType(s, true);
return ConvertResult.Success;
}
}
#if HAVE_BIG_INTEGER
if (targetType == typeof(BigInteger))
{
value = ToBigInteger(initialValue);
return ConvertResult.Success;
}
if (initialValue is BigInteger integer)
{
value = FromBigInteger(integer, targetType);
return ConvertResult.Success;
}
#endif
#if HAVE_TYPE_DESCRIPTOR
// see if source or target types have a TypeConverter that converts between the two
TypeConverter toConverter = TypeDescriptor.GetConverter(initialType);
if (toConverter != null && toConverter.CanConvertTo(targetType))
{
value = toConverter.ConvertTo(null, culture, initialValue, targetType);
return ConvertResult.Success;
}
TypeConverter fromConverter = TypeDescriptor.GetConverter(targetType);
if (fromConverter != null && fromConverter.CanConvertFrom(initialType))
{
value = fromConverter.ConvertFrom(null, culture, initialValue);
return ConvertResult.Success;
}
#endif
#if HAVE_ADO_NET
// handle DBNull
if (initialValue == DBNull.Value)
{
if (ReflectionUtils.IsNullable(targetType))
{
value = EnsureTypeAssignable(null, initialType, targetType);
return ConvertResult.Success;
}
// cannot convert null to non-nullable
value = null;
return ConvertResult.CannotConvertNull;
}
#endif
if (targetType.IsInterface() || targetType.IsGenericTypeDefinition() || targetType.IsAbstract())
{
value = null;
return ConvertResult.NotInstantiableType;
}
value = null;
return ConvertResult.NoValidConversion;
}