diff --git a/src/Mapster.Tests/Mapster.Tests.csproj b/src/Mapster.Tests/Mapster.Tests.csproj index 98ef80bd..6d71cf1c 100644 --- a/src/Mapster.Tests/Mapster.Tests.csproj +++ b/src/Mapster.Tests/Mapster.Tests.csproj @@ -71,6 +71,7 @@ + diff --git a/src/Mapster.Tests/WhenConvertingFromObjects.cs b/src/Mapster.Tests/WhenConvertingFromObjects.cs new file mode 100644 index 00000000..1cc9c753 --- /dev/null +++ b/src/Mapster.Tests/WhenConvertingFromObjects.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; +using Shouldly; + +namespace Mapster.Tests +{ + [TestFixture] + class WhenConvertingFromObjects + { + + #region TestClasses + + public class SimplePoco + { + public int Int32 { get; set; } + public long Int64 { get; set; } + } + + #endregion + + [Test] + public void Int32_In_Object_Is_Converted_To_Int64() + { + var dictionaryData = new Dictionary + { + { "Int32", 32 }, + { "Int64", 64 } + }; + + var poco = dictionaryData.Adapt(); + poco.Int32.ShouldBe(32); + poco.Int64.ShouldBe(64L); + } + } +} diff --git a/src/Mapster/Utils/ReflectionUtils.cs b/src/Mapster/Utils/ReflectionUtils.cs index c9ddfab9..5b3bb997 100644 --- a/src/Mapster/Utils/ReflectionUtils.cs +++ b/src/Mapster/Utils/ReflectionUtils.cs @@ -13,6 +13,24 @@ internal static class ReflectionUtils { private static readonly Type _stringType = typeof (string); + // Primitive types with their conversion methods from System.Convert class. + private static Dictionary _primitiveTypes = new Dictionary() { + { typeof(bool), "ToBoolean" }, + { typeof(short), "ToInt16" }, + { typeof(int), "ToInt32" }, + { typeof(long), "ToInt64" }, + { typeof(float), "ToSingle" }, + { typeof(double), "ToDouble" }, + { typeof(decimal), "ToDecimal" }, + { typeof(ushort), "ToUInt16" }, + { typeof(uint), "ToUInt32" }, + { typeof(ulong), "ToUInt64" }, + { typeof(byte), "ToByte" }, + { typeof(sbyte), "ToSByte" }, + { typeof(DateTime), "ToDateTime" } + }; + + #if NET4 public static Type GetTypeInfo(this Type type) { return type; @@ -55,8 +73,8 @@ public static bool IsCollection(this Type type) public static Type ExtractCollectionType(this Type collectionType) { var enumerableType = collectionType.GetGenericEnumerableType(); - return enumerableType != null - ? enumerableType.GetGenericArguments()[0] + return enumerableType != null + ? enumerableType.GetGenericArguments()[0] : typeof (object); } @@ -69,7 +87,7 @@ public static Type GetInterface(this Type type, Func predicate) { if (predicate(type)) return type; - + return type.GetInterfaces().FirstOrDefault(predicate); } @@ -138,6 +156,11 @@ public static Expression BuildUnderlyingTypeConvertExpression(Expression source, } } + if (IsObjectToPrimitiveConversion(srcType, destType)) + { + return CreateConvertMethod(_primitiveTypes[destType], srcType, destType, source); + } + //try using type casting try { @@ -152,49 +175,20 @@ public static Expression BuildUnderlyingTypeConvertExpression(Expression source, throw new InvalidOperationException("Cannot convert immutable type, please consider using 'MapWith' method to create mapping"); //using Convert - if (destType == typeof (bool)) - return CreateConvertMethod("ToBoolean", srcType, destType, source); - - if (destType == typeof (int)) - return CreateConvertMethod("ToInt32", srcType, destType, source); - - if (destType == typeof (long)) - return CreateConvertMethod("ToInt64", srcType, destType, source); - - if (destType == typeof (short)) - return CreateConvertMethod("ToInt16", srcType, destType, source); - - if (destType == typeof (decimal)) - return CreateConvertMethod("ToDecimal", srcType, destType, source); - - if (destType == typeof (double)) - return CreateConvertMethod("ToDouble", srcType, destType, source); - - if (destType == typeof (float)) - return CreateConvertMethod("ToSingle", srcType, destType, source); - - if (destType == typeof (DateTime)) - return CreateConvertMethod("ToDateTime", srcType, destType, source); - - if (destType == typeof (ulong)) - return CreateConvertMethod("ToUInt64", srcType, destType, source); - - if (destType == typeof (uint)) - return CreateConvertMethod("ToUInt32", srcType, destType, source); - - if (destType == typeof (ushort)) - return CreateConvertMethod("ToUInt16", srcType, destType, source); - - if (destType == typeof (byte)) - return CreateConvertMethod("ToByte", srcType, destType, source); - - if (destType == typeof (sbyte)) - return CreateConvertMethod("ToSByte", srcType, destType, source); + if (_primitiveTypes.ContainsKey(destType)) + { + return CreateConvertMethod(_primitiveTypes[destType], srcType, destType, source); + } var changeTypeMethod = typeof (Convert).GetMethod("ChangeType", new[] {typeof (object), typeof (Type)}); return Expression.Convert(Expression.Call(changeTypeMethod, Expression.Convert(source, typeof (object)), Expression.Constant(destType)), destType); } + private static bool IsObjectToPrimitiveConversion(Type sourceType, Type destinationType) + { + return (sourceType == typeof(object)) && _primitiveTypes.ContainsKey(destinationType); + } + public static MemberExpression GetMemberInfo(Expression method) { var lambda = method as LambdaExpression;