Skip to content

Commit 1d14fc0

Browse files
PanyushkinDPanyushkinD
authored andcommitted
Fix mapping to interface-collections
1 parent 67a898a commit 1d14fc0

4 files changed

Lines changed: 38 additions & 15 deletions

File tree

src/AutoMapper.ExtendedConverters.Tests/CollectionConverterTests.cs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ namespace AutoMapper.ExtendedConverters.Tests
88
[TestClass]
99
public class CollectionConverterTests
1010
{
11-
class Model
11+
public class Model
1212
{
1313
public int Id { get; set; }
1414
public string Text { get; set; }
1515
}
1616

17-
class Entity : IComparable<Entity>
17+
public class Entity : IComparable<Entity>
1818
{
1919
public int Id { get; set; }
2020
public string Text { get; set; }
@@ -33,10 +33,12 @@ public void Initialize()
3333
var config = new MapperConfiguration(cfg => {
3434
cfg.CreateMap<Model, Entity>();
3535

36+
cfg.CreateMap<ModelWrapper, EntityWrapper>();
37+
3638
cfg.CreateMap<Model[], SortedSet<Entity>>()
3739
.UsingCollectionConverter((Model m) => m.Id, (Entity e) => e.Id);
38-
39-
cfg.CreateMap<IEnumerable<Model>, LinkedList<Entity>>()
40+
41+
cfg.CreateMap<IEnumerable<Model>, ICollection<Entity>>()
4042
.UsingCollectionConverter((Model m) => m.Id, (Entity e) => e.Id);
4143
});
4244

@@ -136,10 +138,20 @@ private static IEnumerable<Model> BuildSource()
136138
yield return new Model { Id = 5, Text = "E" };
137139
}
138140

141+
public class ModelWrapper
142+
{
143+
public IEnumerable<Model> Collection { get; set; }
144+
}
145+
146+
public class EntityWrapper
147+
{
148+
public ICollection<Entity> Collection { get; set; }
149+
}
150+
139151
[TestMethod]
140152
public void ShouldMapAnyIEnumerable_ToAnyICollection()
141153
{
142-
ICollection<Entity> dest = new LinkedList<Entity>(new[] {
154+
var dest = new LinkedList<Entity>(new[] {
143155
new Entity { Id = 1, Text = "a" },
144156
new Entity { Id = 2, Text = "b" },
145157
new Entity { Id = 3, Text = "c" },
@@ -148,11 +160,16 @@ public void ShouldMapAnyIEnumerable_ToAnyICollection()
148160
var destArray = new Entity[3];
149161
dest.CopyTo(destArray, 0);
150162

151-
ICollection<Entity> res = Mapper.Map(BuildSource(), dest);
163+
var destWrapper = new EntityWrapper { Collection = dest };
164+
var srcWrapper = new ModelWrapper { Collection = BuildSource() };
165+
166+
var res = Mapper.Map(srcWrapper, destWrapper);
152167

153168
var resArray = new Entity[4];
154-
res.CopyTo(resArray, 0);
169+
res.Collection.CopyTo(resArray, 0);
155170

171+
// should preserve collection type
172+
Assert.AreEqual(dest.GetType(), res.Collection.GetType());
156173
// should preserve objects with keys both in source and destination
157174
Assert.AreSame(destArray[0], resArray[0]);
158175
Assert.AreSame(destArray[1], resArray[1]);
@@ -164,8 +181,8 @@ public void ShouldMapAnyIEnumerable_ToAnyICollection()
164181
Assert.AreNotSame(destArray[2], resArray[3]);
165182

166183
// should map values of collection items
167-
Assert.IsTrue(BuildSource().Select(m => m.Id).SequenceEqual(res.Select(e => e.Id)));
168-
Assert.IsTrue(BuildSource().Select(m => m.Text).SequenceEqual(res.Select(e => e.Text)));
184+
Assert.IsTrue(BuildSource().Select(m => m.Id).SequenceEqual(res.Collection.Select(e => e.Id)));
185+
Assert.IsTrue(BuildSource().Select(m => m.Text).SequenceEqual(res.Collection.Select(e => e.Text)));
169186
}
170187
}
171188
}

src/AutoMapper.ExtendedConverters.Tests/ListConverterTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ namespace AutoMapper.ExtendedConverters.Tests
77
[TestClass]
88
public class ListConverterTests
99
{
10-
class Model
10+
public class Model
1111
{
1212
public int Id { get; set; }
1313
public string Text { get; set; }
1414
}
1515

16-
class Entity
16+
public class Entity
1717
{
1818
public int Id { get; set; }
1919
public string Text { get; set; }
@@ -34,7 +34,7 @@ public void Initialize()
3434

3535
Mapper = config.CreateMapper();
3636
}
37-
37+
3838
[TestMethod]
3939
public void ShouldMapNullSource_WithoutDestination()
4040
{

src/AutoMapper.ExtendedConverters/CollectionConverter.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace AutoMapper.ExtendedConverters
77
public class CollectionConverter<TSrcCollection, TDestCollection, TSrc, TDest, TKey>
88
: ITypeConverter<TSrcCollection, TDestCollection>
99
where TSrcCollection : class, IEnumerable<TSrc>
10-
where TDestCollection : class, ICollection<TDest>, new()
10+
where TDestCollection : class, ICollection<TDest>
1111
{
1212
protected readonly Func<TSrc, TKey> SrcKey;
1313
protected readonly Func<TDest, TKey> DestKey;
@@ -29,13 +29,19 @@ public TDestCollection Convert(ResolutionContext context)
2929

3030
IMapper mapper = context.Engine.Mapper;
3131

32-
var result = new TDestCollection();
32+
TDestCollection result;
3333

3434
if (destCollection == null) {
35+
result = typeof(TDestCollection) == typeof(ICollection<TDest>)
36+
? (TDestCollection)(object)new List<TDest>()
37+
: Activator.CreateInstance<TDestCollection>();
38+
3539
foreach (TSrc src in srcCollection) {
3640
result.Add(mapper.Map<TSrc, TDest>(src));
3741
}
3842
return result;
43+
} else {
44+
result = (TDestCollection)Activator.CreateInstance(destCollection.GetType());
3945
}
4046

4147
ILookup<TKey, TDest> destLookup = destCollection.ToLookup(DestKey);

src/AutoMapper.ExtendedConverters/Extensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public static void UsingCollectionConverter<TSrcCollection, TDestCollection, TSr
2626
Func<TSrc, TKey> srcKey,
2727
Func<TDest, TKey> destKey)
2828
where TSrcCollection : class, IEnumerable<TSrc>
29-
where TDestCollection : class, ICollection<TDest>, new()
29+
where TDestCollection : class, ICollection<TDest>
3030
{
3131
mapping.ConvertUsing(new CollectionConverter<TSrcCollection, TDestCollection, TSrc, TDest, TKey>(srcKey, destKey));
3232
}

0 commit comments

Comments
 (0)