Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit f760cca

Browse files
committed
Use ChangeValueType in AutoMapping Utils + add Exception for long>TimeSpan
1 parent 35dd34a commit f760cca

File tree

2 files changed

+63
-36
lines changed

2 files changed

+63
-36
lines changed

src/ServiceStack.Text/AutoMappingUtils.cs

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,10 @@ public static T ConvertTo<T>(this object from)
2828
if (fromType == typeof(T))
2929
return (T)from;
3030

31-
if (fromType.IsValueType || typeof(T).IsValueType)
31+
var toType = typeof(T);
32+
if (fromType.IsValueType || toType.IsValueType)
3233
{
33-
if (!fromType.IsEnum && !typeof(T).IsEnum)
34-
{
35-
if (typeof(T) == typeof(char) && from is string s)
36-
return (T)(s.Length > 0 ? (object) s[0] : null);
37-
if (typeof(T) == typeof(string) && from is char c)
38-
return (T)(object)c.ToString();
39-
40-
var destNumberType = DynamicNumber.GetNumber(typeof(T));
41-
var value = destNumberType?.ConvertFrom(from);
42-
if (value != null)
43-
{
44-
if (typeof(T) == typeof(char))
45-
return (T)(object)value.ToString()[0];
46-
47-
return (T)value;
48-
}
49-
50-
if (typeof(T) == typeof(string))
51-
{
52-
var srcNumberType = DynamicNumber.GetNumber(from.GetType());
53-
if (srcNumberType != null)
54-
return (T)(object)srcNumberType.ToString(from);
55-
}
56-
}
57-
58-
return (T)ChangeValueType(from, typeof(T));
34+
return (T)ChangeValueType(from, toType);
5935
}
6036

6137
if (typeof(IEnumerable).IsAssignableFrom(typeof(T)))
@@ -113,18 +89,51 @@ public static object ConvertTo(this object from, Type type)
11389
}
11490

11591
var to = type.CreateInstance();
116-
return to.PopulateInstance(from);
92+
return to.PopulateWithNonDefaultValues(from);
11793
}
11894

119-
private static object ChangeValueType(object from, Type type)
95+
public static object ChangeValueType(object from, Type toType)
12096
{
97+
var fromType = from.GetType();
98+
if (!fromType.IsEnum && !toType.IsEnum)
99+
{
100+
if (toType == typeof(char) && from is string s)
101+
return s.Length > 0 ? (object) s[0] : null;
102+
if (toType == typeof(string) && from is char c)
103+
return c.ToString();
104+
if (toType == typeof(TimeSpan) && from is long ticks)
105+
return new TimeSpan(ticks);
106+
107+
var destNumberType = DynamicNumber.GetNumber(toType);
108+
var value = destNumberType?.ConvertFrom(from);
109+
if (value != null)
110+
{
111+
if (toType == typeof(char))
112+
return value.ToString()[0];
113+
114+
return value;
115+
}
116+
117+
if (toType == typeof(string))
118+
{
119+
var srcNumberType = DynamicNumber.GetNumber(from.GetType());
120+
if (srcNumberType != null)
121+
return srcNumberType.ToString(@from);
122+
}
123+
}
124+
121125
if (from is string strValue)
122-
return TypeSerializer.DeserializeFromString(strValue, type);
126+
return TypeSerializer.DeserializeFromString(strValue, toType);
123127

124-
if (type == typeof(string))
128+
if (toType == typeof(string))
125129
return from.ToJsv();
126130

127-
return Convert.ChangeType(from, type, provider: null);
131+
if (toType.HasInterface(typeof(IConvertible)))
132+
{
133+
return Convert.ChangeType(from, toType, provider: null);
134+
}
135+
136+
return TypeSerializer.DeserializeFromString(from.ToJsv(), toType);
128137
}
129138

130139
public static object ChangeTo(this string strValue, Type type)
@@ -149,8 +158,7 @@ public static List<string> GetPropertyNames(this Type type)
149158
{
150159
lock (TypePropertyNamesMap)
151160
{
152-
List<string> propertyNames;
153-
if (!TypePropertyNamesMap.TryGetValue(type, out propertyNames))
161+
if (!TypePropertyNamesMap.TryGetValue(type, out var propertyNames))
154162
{
155163
propertyNames = type.Properties().ToList().ConvertAll(x => x.Name);
156164
TypePropertyNamesMap[type] = propertyNames;
@@ -823,7 +831,7 @@ public static GetMemberDelegate CreateTypeConverter(Type fromType, Type toType)
823831
}
824832
else if (underlyingToType.IsValueType)
825833
{
826-
return fromValue => Convert.ChangeType(fromValue, underlyingToType, provider: null);
834+
return fromValue => AutoMappingUtils.ChangeValueType(fromValue, underlyingToType);
827835
}
828836
else
829837
{

tests/ServiceStack.Text.Tests/AutoMappingObjectDictionaryTests.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Collections.ObjectModel;
34
using System.Linq;
45
using Northwind.Common.DataModel;
@@ -320,6 +321,24 @@ public class ModelWithCollectionsOfNullableTypes
320321
public Car[] Cars { get; set; }
321322
public IList<Color> Colors { get; set; }
322323
}
324+
325+
public class ModelWithTimeSpan
326+
{
327+
public TimeSpan Time { get; set; }
328+
}
329+
330+
[Test]
331+
public void FromObjectDictionary_does_try_to_Convert_different_types()
332+
{
333+
var time = new TimeSpan(1,1,1,1);
334+
var map = new Dictionary<string, object> {
335+
[nameof(ModelWithTimeSpan.Time)] = time.Ticks
336+
};
337+
338+
var dto = map.FromObjectDictionary<ModelWithTimeSpan>();
339+
340+
Assert.That(dto.Time, Is.EqualTo(time));
341+
}
323342
}
324343

325344

0 commit comments

Comments
 (0)