private static Func <Closure, object> Convert(UnaryExpression convertExpression, ConstantExpression[] constantsExprs, ParameterExpression[] localsExprs) { var valueFn = Expression(convertExpression.Operand, constantsExprs, localsExprs); var convertOperator = WrapUnaryOperation(convertExpression.Method) ?? WrapUnaryOperation( convertExpression.Type .GetMethods(BindingFlags.Public | BindingFlags.Static) .FirstOrDefault(m => (string.Equals(m.Name, "op_Explicit", StringComparison.Ordinal) || string.Equals(m.Name, "op_Implicit", StringComparison.Ordinal)) && m.ReturnType == convertExpression.Type && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == convertExpression.Operand.Type) ); var toType = Nullable.GetUnderlyingType(convertExpression.Type) ?? convertExpression.Type; var toIsNullable = Nullable.GetUnderlyingType(convertExpression.Type) != null; var fromType = Nullable.GetUnderlyingType(convertExpression.Operand.Type) ?? convertExpression.Operand.Type; var fromIsNullable = IsNullable(convertExpression.Operand); return(closure => { var value = closure.Unbox <object>(valueFn(closure)); if (value == null && (convertExpression.Type.IsValueType == false || toIsNullable)) { return null; } var convertType = convertExpression.NodeType; if (convertType != ExpressionType.Convert) { convertType = ExpressionType.ConvertChecked; } // un-box if ((fromType == typeof(object) || fromType == typeof(ValueType) || fromType.IsInterface) && toType.IsValueType) { // null un-box if (value == null) { throw new NullReferenceException("Attempt to unbox a null value."); } // typecheck for un-box if (value.GetType() == toType) { return value; } throw new InvalidCastException(); } // box else if (fromType.IsValueType && (toType == typeof(object) || toType == typeof(ValueType) || toType.IsInterface)) { // typecheck for box return toType.IsAssignableFrom(value.GetType()) ? value : null; } // to enum else if (toType.IsEnum && (fromType == typeof(byte) || fromType == typeof(sbyte) || fromType == typeof(short) || fromType == typeof(ushort) || fromType == typeof(int) || fromType == typeof(uint) || fromType == typeof(long) || fromType == typeof(ulong))) { if (value == null) { throw new NullReferenceException("Attempt to unbox a null value."); } value = Intrinsics.Convert(closure, value, Enum.GetUnderlyingType(toType), convertExpression.NodeType, null); return Enum.ToObject(toType, closure.Unbox <object>(value)); } // from enum else if (fromType.IsEnum && (toType == typeof(byte) || toType == typeof(sbyte) || toType == typeof(short) || toType == typeof(ushort) || toType == typeof(int) || toType == typeof(uint) || toType == typeof(long) || toType == typeof(ulong))) { if (value == null) { throw new NullReferenceException("Attempt to unbox a null value."); } value = System.Convert.ChangeType(value, Enum.GetUnderlyingType(fromType)); value = Intrinsics.Convert(closure, value, toType, convertExpression.NodeType, null); return value; } // from nullable if (toType.IsValueType && fromIsNullable) { if (value == null) { throw new NullReferenceException("Attempt to unbox a null value."); } value = Intrinsics.Convert(closure, value, Nullable.GetUnderlyingType(toType) ?? toType, convertExpression.NodeType, null); } else if (toType.IsAssignableFrom(fromType)) { return value; } return Intrinsics.Convert(closure, value, toType, convertType, convertOperator); }); }