private static MethodCallExpression SetValue(ParameterExpression result, Type fromType, Column to, Expression value) { if (to.Type != fromType) { // type if not the same, can it be assigned? if (Types.CanBeCast(fromType, to.Type)) { value = Expression.Convert(value, to.Type); } else if (Types.IsNullable(fromType) && fromType.GetGenericArguments()[0] == to.Type) { value = Expression.Convert(value, to.Type); } else if (Types.IsNullable(fromType) && Types.CanBeCast(fromType.GetGenericArguments()[0], to.Type)) { value = Expression.Convert(value, to.Type); } else { return(null); } } if (to.Type == typeof(byte[])) { var setBytes = typeof(SqlDataRecord).GetMethod("SetBytes", new[] { typeof(int), typeof(long), typeof(byte[]), typeof(int), typeof(int) }); Contract.Assert(setBytes != null); return(Expression.Call(result, setBytes, Expression.Constant(to.Ordinal), Expression.Constant(0L), value, Expression.Constant(0), Expression.PropertyOrField(value, "Length"))); } var setMethod = typeof(SqlDataRecord).GetMethod(SetMethodName(to.Type), new[] { typeof(int), to.Type }); Contract.Assert(setMethod != null); return(Expression.Call(result, setMethod, Expression.Constant(to.Ordinal), value)); }
static Expression ReadValue(ParameterExpression input, Mapping <Thing, Thing> map) { Expression value = Expression.PropertyOrField(input, map.From.Name); var fromType = map.From.Type; var toType = map.To.Type; if (fromType == toType) { return(value); } if (Types.CanBeCast(fromType, toType)) // e.g. int to long { return(Expression.Convert(value, toType)); } if (Types.IsNullable(fromType)) { Expression fromValueOrDefault = Expression.Call(value, fromType.GetMethod("GetValueOrDefault", Type.EmptyTypes)); var fromArgType = Types.NullableOf(fromType); if (fromArgType == toType) // e.g. int? to int { return(fromValueOrDefault); } var cast = Types.GetExplicitCastOperator(fromArgType, toType); if (cast != null) // e.g. IntId<>? to int { return(Expression.Call(cast, fromValueOrDefault)); } if (Types.IsNullable(toType)) { // nullable<> to nullable<> conversion must handle null to null as a special case var toArgType = toType.GetGenericArguments()[0]; if (Types.CanBeCast(fromArgType, toType)) // e.g. int? to long? { return(Expression.Condition(Expression.PropertyOrField(value, "HasValue"), Expression.Convert(fromValueOrDefault, toType), Expression.Default(toType))); } cast = Types.GetExplicitCastOperator(fromArgType, toArgType); // e.g. IntId<>? to int? if (cast != null) { fromValueOrDefault = Expression.Call(cast, fromValueOrDefault); } return(Expression.Condition(Expression.PropertyOrField(value, "HasValue"), Expression.Convert(fromValueOrDefault, toType), Expression.Default(toType))); } if (Types.CanBeCast(fromArgType, toType)) // e.g. int? to long { return(Expression.Convert(fromValueOrDefault, toType)); } } if (Types.IsNullable(toType)) { var toArgType = toType.GetGenericArguments()[0]; var cast2 = Types.GetExplicitCastOperator(fromType, toArgType); // e.g. IntId<> to int? if (cast2 != null) { return(Expression.Convert(Expression.Call(cast2, value), toType)); } } var cast3 = Types.GetExplicitCastOperator(fromType, toType); // e.g. IntId<> to int if (cast3 != null) { return(Expression.Call(cast3, value)); } throw new InvalidOperationException("Should never get here has types compatibility has been checked"); }