/// <summary> /// Checks whether type is primitive or decimal or if nullable types allowed also checks for nullable primitives and nullable decimal. /// </summary> /// <param name="type">The type to check.</param> /// <returns>A boolean determining convert capability,</returns> public virtual bool CanConvert(Type type) { return(type.IsPrimitiveOrDecimal() || type == typeof(string) || (AllowNullableTypes && type.IsNullable(out var nullableBaseType) ? nullableBaseType.IsPrimitiveOrDecimal() : throw TypeConvertHelper.ConvertException(type))); }
/// <summary> /// Create an expression to call <c>Array.Copy</c> to copy arrays. /// </summary> /// <param name="arraySource">The source array.</param> /// <param name="arrayDestination">The destination array.</param> /// <param name="length">A nullable length expression, if null passes </param> /// <returns></returns> /// <exception cref="TypeConvertException"></exception> /// <exception cref="NotImplementedException"></exception> public static Expression CreateCopyArrayExpression(Expression arraySource, Expression arrayDestination, Expression length) { if (!arraySource.Type.IsArray || !arrayDestination.Type.IsArray) { throw TypeConvertHelper.ConvertException(arraySource.Type, arrayDestination.Type); } var sourceElementType = arraySource.Type.GetElementType().GetTypeOrNullableBaseType(); //TODO: add IConvertible support //TSource must be array and same as TDestination //Source's rank must be 1 //TSource must be primitive or decimal or object if (arraySource.Type.GetElementType() == arrayDestination.Type.GetElementType() && arraySource.Type.GetArrayRank() == 1 && ( sourceElementType.IsPrimitive || sourceElementType == typeof(object) || sourceElementType == typeof(decimal) ) ) { //Array.Copy(source, destination, Math.Floor(source.Length, destination.Length)) if (length == null) { //Math.Min(source.Length, destination.Length) length = Expression.Call( typeof(System.Math).GetMethod(nameof(System.Math.Min), new[] { typeof(int), typeof(int) }), //int Math.Min(int) Expression.ArrayLength(arraySource), //source.Length Expression.ArrayLength(arrayDestination) //destination.Length ); } var block = Expression.Call( typeof(Array).GetMethod(nameof(Array.Copy), new[] { typeof(Array), typeof(Array), typeof(int) }), //Array.Copy(Array, Array, int) arraySource, arrayDestination, length ); return(block); } else { throw new NotImplementedException(); } }
public static Expression ConvertInlineExpressionAllowNullable(Expression source, Type destinationType) { var convert = source; var sourceType = source.Type; if (sourceType != destinationType) { if (sourceType.IsNullable(out var nullableBaseType)) { convert = Expression.Convert(convert, nullableBaseType); //src == null ? default(TDestination) : {convert}(src) var compareNull = Expression.Equal(convert, Expression.Constant(null, sourceType)); convert = Expression.Condition(compareNull, Expression.Default(destinationType), convert); } else if (sourceType.IsPrimitiveOrDecimal()) { convert = Expression.Convert(convert, destinationType); } else if (sourceType.IsConvertible()) { MethodInfo convertMethodInfo; if (TypeConvertHelper.ConvertMethodNameMapping.TryGetValue(destinationType, out var methodName) && (convertMethodInfo = typeof(System.Convert).GetMethod(methodName, new[] { sourceType })) != null ) { //Convert.To{DestinationType}(source) convert = Expression.Call(convertMethodInfo, convert); } else { convertMethodInfo = typeof(System.Convert).GetMethod(nameof(System.Convert.ChangeType), new[] { typeof(object), typeof(Type) }); convert = Expression.Call(convertMethodInfo, Expression.Convert(source, typeof(object)), Expression.Constant(destinationType)); convert = Expression.Convert(convert, destinationType); } } else { throw TypeConvertHelper.ConvertException(sourceType, destinationType); } } return(convert); }
public static Expression CreateToArrayExpression(Expression enumerableSource, Type destinationType) { if (!typeof(IEnumerable).IsAssignableFrom(enumerableSource.Type)) { throw TypeConvertHelper.ConvertException(enumerableSource.Type, destinationType); } if (destinationType == null) { destinationType = enumerableSource.Type.GetEnumerableBaseType(); } //source.ToArray() var toArray = Expression.Call( typeof(Enumerable).GetMethod(nameof(Enumerable.ToArray)), enumerableSource ); return(toArray); }