private Expression PromoteExpression(Expression expr, Type type, bool exact)
{
if (expr.Type == type) return expr;
var ce = expr as ConstantExpression;
if (ce != null)
{
if (ce == NullLiteral)
{
if (!type.IsValueType || IsNullableType(type))
return Expression.Constant(null, type);
}
else
{
string text;
if (_literals.TryGetValue(ce, out text))
{
Type target = GetNonNullableType(type);
object value = null;
switch (Type.GetTypeCode(ce.Type))
{
case TypeCode.Int32:
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
value = ParseNumber(text, target);
break;
case TypeCode.Double:
if (target == typeof(decimal)) value = ParseNumber(text, target);
break;
case TypeCode.String:
value = ParseEnum(text, target);
break;
}
if (value != null)
return Expression.Constant(value, type);
}
}
}
if (IsCompatibleWith(expr.Type, type))
{
if (type.IsValueType || exact) return Expression.Convert(expr, type);
return expr;
}
if (expr.Type == typeof(char) && type == typeof(string))
{
return Expression.Call(expr, "ToString", Type.EmptyTypes);
}
return null;
}