private static bool IsCompatibleWith(Type source, Type target)
{
if (source == target) return true;
if (!target.IsValueType) return target.IsAssignableFrom(source);
Type st = GetNonNullableType(source);
Type tt = GetNonNullableType(target);
if (st != source && tt == target) return false;
TypeCode sc = st.IsEnum ? TypeCode.Object : Type.GetTypeCode(st);
TypeCode tc = tt.IsEnum ? TypeCode.Object : Type.GetTypeCode(tt);
switch (sc)
{
case TypeCode.SByte:
switch (tc)
{
case TypeCode.SByte:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
break;
case TypeCode.Byte:
switch (tc)
{
case TypeCode.Byte:
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;
}
break;
case TypeCode.Int16:
switch (tc)
{
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
break;
case TypeCode.UInt16:
switch (tc)
{
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;
}
break;
case TypeCode.Int32:
switch (tc)
{
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
break;
case TypeCode.UInt32:
switch (tc)
{
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
break;
case TypeCode.Int64:
switch (tc)
{
case TypeCode.Int64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
break;
case TypeCode.UInt64:
switch (tc)
{
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return true;
}
break;
case TypeCode.Single:
switch (tc)
{
case TypeCode.Single:
case TypeCode.Double:
return true;
}
break;
case TypeCode.Decimal:
switch (tc)
{
case TypeCode.Decimal:
case TypeCode.Single:
case TypeCode.Double:
return true;
}
break;
default:
if (st == tt) return true;
break;
}
return false;
}