Skip to content

Commit e095877

Browse files
committed
Adding null-checking and empty collection creation to ValueInjector deep and complex mappers
1 parent 1911ef7 commit e095877

File tree

2 files changed

+96
-3
lines changed

2 files changed

+96
-3
lines changed
Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,104 @@
11
namespace AgileObjects.AgileMapper.PerformanceTester.ConcreteMappers.ValueInjecter
22
{
3+
using System;
4+
using System.Collections;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Reflection;
38
using AbstractMappers;
49
using Omu.ValueInjecter;
10+
using Omu.ValueInjecter.Injections;
511
using TestClasses;
612

713
internal class ValueInjecterComplexTypeMapper : ComplexTypeMapperBase
814
{
915
public override void Initialise()
1016
{
17+
Mapper.AddMap<List<Foo>, List<Foo>>(foos => foos != null ? Mapper.Map<List<Foo>>(foos) : new List<Foo>());
1118
}
1219

1320
protected override Foo Clone(Foo foo)
1421
{
15-
return Mapper.Map<Foo>(foo);
22+
return (Foo)new Foo().InjectFrom<CloneInjection>(foo);
23+
}
24+
25+
public class CloneInjection : LoopInjection
26+
{
27+
protected override void Execute(PropertyInfo sp, object source, object target)
28+
{
29+
var tp = target.GetType().GetProperty(sp.Name);
30+
if (tp == null) return;
31+
var val = sp.GetValue(source);
32+
33+
tp.SetValue(target, GetClone(sp, val));
34+
}
35+
36+
private static object GetClone(PropertyInfo sp, object val)
37+
{
38+
if (sp.PropertyType.IsValueType || sp.PropertyType == typeof(string))
39+
{
40+
return val;
41+
}
42+
43+
if (sp.PropertyType.IsArray)
44+
{
45+
if (val == null)
46+
{
47+
return Array.CreateInstance(sp.PropertyType.GetElementType(), 0);
48+
}
49+
50+
var arr = val as Array;
51+
var arrClone = arr.Clone() as Array;
52+
53+
for (int index = 0; index < arr.Length; index++)
54+
{
55+
var a = arr.GetValue(index);
56+
if (a.GetType().IsValueType || a is string) continue;
57+
58+
arrClone.SetValue(Activator.CreateInstance(a.GetType()).InjectFrom<CloneInjection>(a), index);
59+
}
60+
61+
return arrClone;
62+
}
63+
64+
if (sp.PropertyType.IsGenericType)
65+
{
66+
//handle IEnumerable<> also ICollection<> IList<> List<>
67+
if (sp.PropertyType.GetGenericTypeDefinition().GetInterfaces().Contains(typeof(IEnumerable)))
68+
{
69+
var genericType = sp.PropertyType.GetGenericArguments()[0];
70+
var listType = typeof(List<>).MakeGenericType(genericType);
71+
72+
if (val == null)
73+
{
74+
return Activator.CreateInstance(listType);
75+
}
76+
77+
var list = Activator.CreateInstance(listType);
78+
79+
var addMethod = listType.GetMethod("Add");
80+
foreach (var o in val as IEnumerable)
81+
{
82+
var listItem = genericType.IsValueType || genericType == typeof(string) ? o : Activator.CreateInstance(genericType).InjectFrom<CloneInjection>(o);
83+
addMethod.Invoke(list, new[] { listItem });
84+
}
85+
86+
return list;
87+
}
88+
89+
//unhandled generic type, you could also return null or throw
90+
return val;
91+
}
92+
93+
if (val == null)
94+
{
95+
return null;
96+
}
97+
98+
//for simple object types create a new instace and apply the clone injection on it
99+
return Activator.CreateInstance(sp.PropertyType)
100+
.InjectFrom<CloneInjection>(val);
101+
}
16102
}
17103
}
18104
}

AgileMapper.PerformanceTester/ConcreteMappers/ValueInjecter/ValueInjecterDeepMapper.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace AgileObjects.AgileMapper.PerformanceTester.ConcreteMappers.ValueInjecter
22
{
3+
using System.Collections.Generic;
34
using System.Linq;
45
using AbstractMappers;
56
using Omu.ValueInjecter;
@@ -16,8 +17,14 @@ protected override CustomerDto Map(Customer customer)
1617
{
1718
var dto = (CustomerDto)new CustomerDto().InjectFrom<FlatLoopInjection>(customer);
1819
dto.HomeAddress = (AddressDto)new AddressDto().InjectFrom(customer.HomeAddress);
19-
dto.Addresses = customer.Addresses.Select(a => (AddressDto)new AddressDto().InjectFrom(a)).ToList();
20-
dto.AddressesArray = customer.AddressesArray.Select(a => (AddressDto)new AddressDto().InjectFrom(a)).ToArray();
20+
21+
dto.Addresses =
22+
customer.Addresses?.Select(a => (AddressDto)new AddressDto().InjectFrom(a)).ToList()
23+
?? new List<AddressDto>();
24+
25+
dto.AddressesArray =
26+
customer.AddressesArray?.Select(a => (AddressDto)new AddressDto().InjectFrom(a)).ToArray()
27+
?? new AddressDto[0];
2128

2229
return dto;
2330
}

0 commit comments

Comments
 (0)