Skip to content

Commit 884abff

Browse files
authored
ISet support, re: #92 (#94)
* Supporting ISet<T>, re: #92 * Support for merging ISet<T>s
1 parent 3d9c537 commit 884abff

File tree

5 files changed

+69
-14
lines changed

5 files changed

+69
-14
lines changed

AgileMapper.UnitTests/WhenMappingOnToEnumerableMembers.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,35 @@ public void ShouldMergeAnIdentifiableComplexTypeIReadOnlyCollectionArray()
201201
result.Value.Second().Price.ShouldBe(1000.00);
202202
result.Value.ShouldBe(r => r.ProductId, "Magic", "Science");
203203
}
204+
205+
[Fact]
206+
public void ShouldMergeAnIdentifiableComplexTypeSet()
207+
{
208+
var source = new PublicField<Product[]>
209+
{
210+
Value = new Product[]
211+
{
212+
new MegaProduct { ProductId = "Science", Price = 1000.00 }
213+
}
214+
};
215+
216+
var target = new PublicField<ISet<MegaProduct>>
217+
{
218+
Value = new HashSet<MegaProduct>
219+
{
220+
new MegaProduct { ProductId = "Magic", Price = 1.00 },
221+
new MegaProduct { ProductId = "Science" }
222+
}
223+
};
224+
225+
var existingProduct = target.Value.Second();
226+
var result = Mapper.Map(source).OnTo(target);
227+
228+
result.Value.ShouldBeSameAs(target.Value);
229+
result.Value.Second().ShouldBeSameAs(existingProduct);
230+
result.Value.Second().Price.ShouldBe(1000.00);
231+
result.Value.ShouldBe(r => r.ProductId, "Magic", "Science");
232+
}
204233
#endif
205234
[Fact]
206235
public void ShouldHandleANullSourceMember()

AgileMapper.UnitTests/WhenMappingToNewEnumerables.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ public void ShouldCreateAnIReadOnlyCollection()
127127
result.ShouldBe((short)1, (short)2, (short)3);
128128
}
129129
#endif
130-
131130
[Fact]
132131
public void ShouldMapFromAHashset()
133132
{
@@ -142,6 +141,17 @@ public void ShouldMapFromAHashset()
142141
result.ShouldBe(yesterday, today, tomorrow);
143142
}
144143

144+
#if !NET35
145+
[Fact]
146+
public void ShouldMapToAnISet()
147+
{
148+
var source = new[] { "1", "2", "3" };
149+
var result = Mapper.Map(source).ToANew<ISet<long>>();
150+
151+
result.ShouldNotBeNull();
152+
result.ShouldBe(1L, 2L, 3L);
153+
}
154+
#endif
145155
[Fact]
146156
public void ShouldHandleANullComplexTypeElement()
147157
{

AgileMapper/AgileMapper.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
</ItemGroup>
4545

4646
<PropertyGroup Condition=" '$(TargetFramework)' == 'net40' ">
47-
<DefineConstants>$(DefineConstants);FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_COLLECTION_CAPACITY;NET_40;</DefineConstants>
47+
<DefineConstants>$(DefineConstants);FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_COLLECTION_CAPACITY;FEATURE_ISET;NET_40;</DefineConstants>
4848
</PropertyGroup>
4949

5050
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.0' ">
@@ -55,7 +55,7 @@
5555
</ItemGroup>
5656

5757
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.0' ">
58-
<DefineConstants>$(DefineConstants);NET_STANDARD;FEATURE_DYNAMIC;NET_STANDARD_1;</DefineConstants>
58+
<DefineConstants>$(DefineConstants);NET_STANDARD;FEATURE_DYNAMIC;FEATURE_ISET;NET_STANDARD_1;</DefineConstants>
5959
</PropertyGroup>
6060

6161
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
@@ -67,7 +67,7 @@
6767
</ItemGroup>
6868

6969
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
70-
<DefineConstants>$(DefineConstants);NET_STANDARD;FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_COLLECTION_CAPACITY;NET_STANDARD_2;</DefineConstants>
70+
<DefineConstants>$(DefineConstants);NET_STANDARD;FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_COLLECTION_CAPACITY;FEATURE_ISET;NET_STANDARD_2;</DefineConstants>
7171
</PropertyGroup>
7272

7373
</Project>

AgileMapper/ObjectPopulation/Enumerables/EnumerablePopulationBuilder.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ private Expression GetTargetVariableValue()
379379

380380
if (MapperData.TargetIsDefinitelyUnpopulated())
381381
{
382-
return GetNullTargetListConstruction();
382+
return GetNullTargetConstruction();
383383
}
384384

385385
if (_sourceAdapter.UseReadOnlyTargetWrapper)
@@ -415,7 +415,7 @@ private Expression GetTargetVariableValue()
415415
return nonNullTargetVariableValue;
416416
}
417417

418-
var nullTargetVariableValue = GetNullTargetListConstruction();
418+
var nullTargetVariableValue = GetNullTargetConstruction();
419419

420420
var targetVariableValue = Expression.Condition(
421421
MapperData.TargetObject.GetIsNotDefaultComparison(),
@@ -429,21 +429,21 @@ private Expression GetTargetVariableValue()
429429
private Expression GetCopyIntoWrapperConstruction()
430430
=> TargetTypeHelper.GetWrapperConstruction(MapperData.TargetObject, GetSourceCountAccess());
431431

432-
private Expression GetNullTargetListConstruction()
432+
private Expression GetNullTargetConstruction()
433433
{
434434
var nonNullTargetVariableType =
435435
(TargetTypeHelper.IsDeclaredReadOnly ? TargetTypeHelper.ListType : MapperData.TargetType);
436436

437437
var nullTargetVariableType = GetNullTargetVariableType(nonNullTargetVariableType);
438438

439+
#if FEATURE_COLLECTION_CAPACITY
439440
return SourceTypeHelper.IsEnumerableInterface || TargetTypeHelper.IsCollection
440441
? Expression.New(nullTargetVariableType)
441-
#if FEATURE_COLLECTION_CAPACITY
442442
: Expression.New(
443443
nullTargetVariableType.GetPublicInstanceConstructor(typeof(int)),
444444
GetSourceCountAccess());
445445
#else
446-
: Expression.New(nullTargetVariableType.GetPublicInstanceConstructor());
446+
return Expression.New(nullTargetVariableType);
447447
#endif
448448
}
449449

@@ -493,7 +493,13 @@ private Expression GetCopyIntoObjectConstruction()
493493
private Type GetNullTargetVariableType(Type nonNullTargetVariableType)
494494
{
495495
return nonNullTargetVariableType.IsInterface()
496+
#if FEATURE_ISET
497+
? nonNullTargetVariableType.IsClosedTypeOf(typeof(ISet<>))
498+
? TargetTypeHelper.HashSetType
499+
: TargetTypeHelper.ListType
500+
#else
496501
? TargetTypeHelper.ListType
502+
#endif
497503
: nonNullTargetVariableType;
498504
}
499505

AgileMapper/ObjectPopulation/Enumerables/EnumerableTypeHelper.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ internal class EnumerableTypeHelper
2222
private Type _readOnlyCollectionType;
2323
private Type _collectionInterfaceType;
2424
private Type _enumerableInterfaceType;
25-
25+
#if FEATURE_ISET
26+
private Type _setInterfaceType;
27+
#endif
2628
public EnumerableTypeHelper(IQualifiedMember member)
2729
: this(member.Type, member.ElementType)
2830
{
@@ -45,14 +47,19 @@ public bool IsDictionary
4547

4648
public bool IsCollection => EnumerableType.IsAssignableTo(CollectionType);
4749

48-
public bool IsHashSet => EnumerableType == HashSetType;
50+
private bool IsHashSet => EnumerableType == HashSetType;
4951

5052
public bool IsReadOnlyCollection => EnumerableType == ReadOnlyCollectionType;
5153

5254
public bool IsEnumerableInterface => EnumerableType == EnumerableInterfaceType;
5355

5456
public bool HasCollectionInterface => EnumerableType.IsAssignableTo(CollectionInterfaceType);
5557

58+
#if FEATURE_ISET
59+
private bool HasSetInterface => EnumerableType.IsAssignableTo(SetInterfaceType);
60+
#else
61+
private bool HasSetInterface => IsHashSet;
62+
#endif
5663
public bool IsReadOnly => IsArray || IsReadOnlyCollection;
5764

5865
public bool IsDeclaredReadOnly
@@ -89,6 +96,9 @@ private bool IsReadOnlyCollectionInterface()
8996

9097
public Type EnumerableInterfaceType => GetEnumerableType(ref _enumerableInterfaceType, typeof(IEnumerable<>));
9198

99+
#if FEATURE_ISET
100+
private Type SetInterfaceType => GetEnumerableType(ref _setInterfaceType, typeof(ISet<>));
101+
#endif
92102
private Type GetEnumerableType(ref Type typeField, Type openGenericEnumerableType)
93103
=> typeField ?? (typeField = openGenericEnumerableType.MakeGenericType(ElementType));
94104

@@ -113,7 +123,7 @@ public Expression GetEmptyInstanceCreation(Type enumerableType = null)
113123

114124
public Expression GetCopyIntoObjectConstruction(Expression targetObject)
115125
{
116-
var objectType = IsHashSet ? HashSetType : ListType;
126+
var objectType = HasSetInterface ? HashSetType : ListType;
117127

118128
return Expression.New(
119129
objectType.GetPublicInstanceConstructor(EnumerableInterfaceType),
@@ -151,7 +161,7 @@ public Expression GetEnumerableConversion(Expression instance, bool allowEnumera
151161
return instance.WithToCollectionCall(ElementType);
152162
}
153163

154-
return instance.WithToListLinqCall(ElementType);
164+
return GetCopyIntoObjectConstruction(instance);
155165
}
156166

157167
private static bool ValueIsNotEnumerableInterface(Expression instance)
@@ -166,7 +176,7 @@ public Type GetEmptyInstanceCreationFallbackType()
166176
? EnumerableType.GetDictionaryConcreteType()
167177
: IsCollection
168178
? CollectionType
169-
: IsHashSet
179+
: HasSetInterface
170180
? HashSetType
171181
: ListType;
172182
}

0 commit comments

Comments
 (0)