2025-03-10 10:18:11 +08:00

152 lines
5.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace FlexFramework.Excel
{
public static class Validator
{
public static bool CanCast(Type from, Type to)
{
if (from.IsAssignableFrom(to))
{
return true;
}
if (HasImplicitConversion(from, to) || HasImplicitConversion(from, from, to) || HasImplicitConversion(to, from, to))
{
return true;
}
if (to.IsEnum)
{
return CanCast(from, Enum.GetUnderlyingType(to));
}
if (Nullable.GetUnderlyingType(to) != null)
{
return CanCast(from, Nullable.GetUnderlyingType(to));
}
return false;
}
static bool HasImplicitConversion(Type definedOn, Type baseType, Type targetType)
{
return definedOn.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Where(m => m.Name == "op_Implicit" && m.ReturnType == targetType)
.Any(m =>
{
var p = m.GetParameters().FirstOrDefault();
return p != null && p.ParameterType == baseType;
});
}
public static bool HasImplicitConversion(Type source, Type target)
{
var sourceCode = Type.GetTypeCode(source);
var targetCode = Type.GetTypeCode(target);
switch (sourceCode)
{
case TypeCode.SByte:
switch (targetCode)
{
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
return false;
case TypeCode.Byte:
switch (targetCode)
{
case TypeCode.Int16:
case TypeCode.UInt16:
case TypeCode.Int32:
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
return false;
case TypeCode.Int16:
switch (targetCode)
{
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
return false;
case TypeCode.UInt16:
switch (targetCode)
{
case TypeCode.Int32:
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
return false;
case TypeCode.Int32:
switch (targetCode)
{
case TypeCode.Int64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
return false;
case TypeCode.UInt32:
switch (targetCode)
{
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
return false;
case TypeCode.Int64:
case TypeCode.UInt64:
switch (targetCode)
{
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
return false;
case TypeCode.Char:
switch (targetCode)
{
case TypeCode.UInt16:
case TypeCode.Int32:
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
return false;
case TypeCode.Single:
return (targetCode == TypeCode.Double);
}
return false;
}
}
}