using System;
using System.ComponentModel;
using System.Globalization;
namespace Masuit.Tools;
public static class IConvertibleExtensions
{
public static bool IsNumeric(this Type type)
{
switch (Type.GetTypeCode(type))
{
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single:
return true;
default:
return false;
}
}
///
/// 类型直转
///
///
///
///
public static T ConvertTo(this IConvertible value) where T : IConvertible
{
if (value != null)
{
var type = typeof(T);
if (value.GetType() == type)
{
return (T)value;
}
if (type.IsEnum)
{
return (T)Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
}
if (value == DBNull.Value)
{
return default;
}
if (type.IsNumeric())
{
return (T)value.ToType(type, new NumberFormatInfo());
}
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
var underlyingType = Nullable.GetUnderlyingType(type);
return (T)(underlyingType!.IsEnum ? Enum.Parse(underlyingType, value.ToString(CultureInfo.CurrentCulture)) : Convert.ChangeType(value, underlyingType));
}
var converter = TypeDescriptor.GetConverter(value);
if (converter.CanConvertTo(type))
{
return (T)converter.ConvertTo(value, type);
}
converter = TypeDescriptor.GetConverter(type);
if (converter.CanConvertFrom(value.GetType()))
{
return (T)converter.ConvertFrom(value);
}
return (T)Convert.ChangeType(value, type);
}
return (T)value;
}
///
/// 类型直转
///
///
///
/// 转换失败的默认值
///
public static T TryConvertTo(this IConvertible value, T defaultValue = default) where T : IConvertible
{
try
{
return ConvertTo(value);
}
catch
{
return defaultValue;
}
}
///
/// 类型直转
///
///
///
/// 转换失败的默认值
///
public static bool TryConvertTo(this IConvertible value, out T result) where T : IConvertible
{
try
{
result = ConvertTo(value);
return true;
}
catch
{
result = default;
return false;
}
}
///
/// 类型直转
///
///
/// 目标类型
/// 转换失败的默认值
///
public static bool TryConvertTo(this IConvertible value, Type type, out object result)
{
try
{
result = ConvertTo(value, type);
return true;
}
catch
{
result = null;
return false;
}
}
///
/// 类型直转
///
///
/// 目标类型
///
public static object ConvertTo(this IConvertible value, Type type)
{
if (value == null)
{
return null;
}
if (value.GetType() == type)
{
return value;
}
if (value == DBNull.Value)
{
return null;
}
if (type.IsAssignableFrom(typeof(string)))
{
return value.ToString();
}
if (type.IsEnum)
{
return Enum.Parse(type, value.ToString(CultureInfo.InvariantCulture));
}
if (type.IsAssignableFrom(typeof(Guid)))
{
return Guid.Parse(value.ToString());
}
if (type.IsAssignableFrom(typeof(DateTime)))
{
return DateTime.Parse(value.ToString());
}
if (type.IsAssignableFrom(typeof(DateTimeOffset)))
{
return DateTimeOffset.Parse(value.ToString());
}
if (type.IsNumeric())
{
return value.ToType(type, new NumberFormatInfo());
}
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
var underlyingType = Nullable.GetUnderlyingType(type);
return underlyingType!.IsEnum ? Enum.Parse(underlyingType, value.ToString(CultureInfo.CurrentCulture)) : Convert.ChangeType(value, underlyingType);
}
var converter = TypeDescriptor.GetConverter(value);
if (converter.CanConvertTo(type))
{
return converter.ConvertTo(value, type);
}
converter = TypeDescriptor.GetConverter(type);
return converter.CanConvertFrom(value.GetType()) ? converter.ConvertFrom(value) : Convert.ChangeType(value, type);
}
///
/// 对象类型转换
///
/// 当前值
/// 转换后的对象
public static T ChangeTypeTo(this object @this)
{
return (T)ChangeType(@this, typeof(T));
}
///
/// 对象类型转换
///
/// 当前值
/// 默认值
/// 转换后的对象
public static T ChangeTypeTo(this object @this, T defaultValue)
{
return @this == null ? defaultValue : (T)ChangeType(@this, typeof(T));
}
///
/// 对象类型转换
///
/// 当前值
/// 指定类型的类型
/// 转换后的对象
public static object ChangeType(this object @this, Type type)
{
var currType = Nullable.GetUnderlyingType(@this.GetType()) ?? @this.GetType();
type = Nullable.GetUnderlyingType(type) ?? type;
if (@this == DBNull.Value)
{
if (!type.IsValueType)
{
return null;
}
throw new Exception("不能将null值转换为" + type.Name + "类型!");
}
if (currType == type)
{
return @this;
}
if (type.IsAssignableFrom(typeof(string)))
{
return @this.ToString();
}
if (type.IsEnum)
{
return Enum.Parse(type, @this.ToString(), true);
}
if (type.IsAssignableFrom(typeof(Guid)))
{
return Guid.Parse(@this.ToString());
}
if (!type.IsArray || !currType.IsArray)
{
return Convert.ChangeType(@this, type);
}
var length = ((Array)@this).Length;
var targetType = Type.GetType(type.FullName.Trim('[', ']'));
var array = Array.CreateInstance(targetType, length);
for (int j = 0; j < length; j++)
{
var tmp = ((Array)@this).GetValue(j);
array.SetValue(ChangeType(tmp, targetType), j);
}
return array;
}
}