Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions AgileMapper.UnitTests/WhenMappingOnToEnumerableMembers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,35 @@ public void ShouldMergeAnIdentifiableComplexTypeIReadOnlyCollectionArray()
result.Value.Second().Price.ShouldBe(1000.00);
result.Value.ShouldBe(r => r.ProductId, "Magic", "Science");
}

[Fact]
public void ShouldMergeAnIdentifiableComplexTypeSet()
{
var source = new PublicField<Product[]>
{
Value = new Product[]
{
new MegaProduct { ProductId = "Science", Price = 1000.00 }
}
};

var target = new PublicField<ISet<MegaProduct>>
{
Value = new HashSet<MegaProduct>
{
new MegaProduct { ProductId = "Magic", Price = 1.00 },
new MegaProduct { ProductId = "Science" }
}
};

var existingProduct = target.Value.Second();
var result = Mapper.Map(source).OnTo(target);

result.Value.ShouldBeSameAs(target.Value);
result.Value.Second().ShouldBeSameAs(existingProduct);
result.Value.Second().Price.ShouldBe(1000.00);
result.Value.ShouldBe(r => r.ProductId, "Magic", "Science");
}
#endif
[Fact]
public void ShouldHandleANullSourceMember()
Expand Down
12 changes: 11 additions & 1 deletion AgileMapper.UnitTests/WhenMappingToNewEnumerables.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ public void ShouldCreateAnIReadOnlyCollection()
result.ShouldBe((short)1, (short)2, (short)3);
}
#endif

[Fact]
public void ShouldMapFromAHashset()
{
Expand All @@ -142,6 +141,17 @@ public void ShouldMapFromAHashset()
result.ShouldBe(yesterday, today, tomorrow);
}

#if !NET35
[Fact]
public void ShouldMapToAnISet()
{
var source = new[] { "1", "2", "3" };
var result = Mapper.Map(source).ToANew<ISet<long>>();

result.ShouldNotBeNull();
result.ShouldBe(1L, 2L, 3L);
}
#endif
[Fact]
public void ShouldHandleANullComplexTypeElement()
{
Expand Down
6 changes: 3 additions & 3 deletions AgileMapper/AgileMapper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
</ItemGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net40' ">
<DefineConstants>$(DefineConstants);FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_COLLECTION_CAPACITY;NET_40;</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_COLLECTION_CAPACITY;FEATURE_ISET;NET_40;</DefineConstants>
</PropertyGroup>

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

<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.0' ">
<DefineConstants>$(DefineConstants);NET_STANDARD;FEATURE_DYNAMIC;NET_STANDARD_1;</DefineConstants>
<DefineConstants>$(DefineConstants);NET_STANDARD;FEATURE_DYNAMIC;FEATURE_ISET;NET_STANDARD_1;</DefineConstants>
</PropertyGroup>

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

<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<DefineConstants>$(DefineConstants);NET_STANDARD;FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_COLLECTION_CAPACITY;NET_STANDARD_2;</DefineConstants>
<DefineConstants>$(DefineConstants);NET_STANDARD;FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_COLLECTION_CAPACITY;FEATURE_ISET;NET_STANDARD_2;</DefineConstants>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ private Expression GetTargetVariableValue()

if (MapperData.TargetIsDefinitelyUnpopulated())
{
return GetNullTargetListConstruction();
return GetNullTargetConstruction();
}

if (_sourceAdapter.UseReadOnlyTargetWrapper)
Expand Down Expand Up @@ -415,7 +415,7 @@ private Expression GetTargetVariableValue()
return nonNullTargetVariableValue;
}

var nullTargetVariableValue = GetNullTargetListConstruction();
var nullTargetVariableValue = GetNullTargetConstruction();

var targetVariableValue = Expression.Condition(
MapperData.TargetObject.GetIsNotDefaultComparison(),
Expand All @@ -429,21 +429,21 @@ private Expression GetTargetVariableValue()
private Expression GetCopyIntoWrapperConstruction()
=> TargetTypeHelper.GetWrapperConstruction(MapperData.TargetObject, GetSourceCountAccess());

private Expression GetNullTargetListConstruction()
private Expression GetNullTargetConstruction()
{
var nonNullTargetVariableType =
(TargetTypeHelper.IsDeclaredReadOnly ? TargetTypeHelper.ListType : MapperData.TargetType);

var nullTargetVariableType = GetNullTargetVariableType(nonNullTargetVariableType);

#if FEATURE_COLLECTION_CAPACITY
return SourceTypeHelper.IsEnumerableInterface || TargetTypeHelper.IsCollection
? Expression.New(nullTargetVariableType)
#if FEATURE_COLLECTION_CAPACITY
: Expression.New(
nullTargetVariableType.GetPublicInstanceConstructor(typeof(int)),
GetSourceCountAccess());
#else
: Expression.New(nullTargetVariableType.GetPublicInstanceConstructor());
return Expression.New(nullTargetVariableType);
#endif
}

Expand Down Expand Up @@ -493,7 +493,13 @@ private Expression GetCopyIntoObjectConstruction()
private Type GetNullTargetVariableType(Type nonNullTargetVariableType)
{
return nonNullTargetVariableType.IsInterface()
#if FEATURE_ISET
? nonNullTargetVariableType.IsClosedTypeOf(typeof(ISet<>))
? TargetTypeHelper.HashSetType
: TargetTypeHelper.ListType
#else
? TargetTypeHelper.ListType
#endif
: nonNullTargetVariableType;
}

Expand Down
20 changes: 15 additions & 5 deletions AgileMapper/ObjectPopulation/Enumerables/EnumerableTypeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ internal class EnumerableTypeHelper
private Type _readOnlyCollectionType;
private Type _collectionInterfaceType;
private Type _enumerableInterfaceType;

#if FEATURE_ISET
private Type _setInterfaceType;
#endif
public EnumerableTypeHelper(IQualifiedMember member)
: this(member.Type, member.ElementType)
{
Expand All @@ -45,14 +47,19 @@ public bool IsDictionary

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

public bool IsHashSet => EnumerableType == HashSetType;
private bool IsHashSet => EnumerableType == HashSetType;

public bool IsReadOnlyCollection => EnumerableType == ReadOnlyCollectionType;

public bool IsEnumerableInterface => EnumerableType == EnumerableInterfaceType;

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

#if FEATURE_ISET
private bool HasSetInterface => EnumerableType.IsAssignableTo(SetInterfaceType);
#else
private bool HasSetInterface => IsHashSet;
#endif
public bool IsReadOnly => IsArray || IsReadOnlyCollection;

public bool IsDeclaredReadOnly
Expand Down Expand Up @@ -89,6 +96,9 @@ private bool IsReadOnlyCollectionInterface()

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

#if FEATURE_ISET
private Type SetInterfaceType => GetEnumerableType(ref _setInterfaceType, typeof(ISet<>));
#endif
private Type GetEnumerableType(ref Type typeField, Type openGenericEnumerableType)
=> typeField ?? (typeField = openGenericEnumerableType.MakeGenericType(ElementType));

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

public Expression GetCopyIntoObjectConstruction(Expression targetObject)
{
var objectType = IsHashSet ? HashSetType : ListType;
var objectType = HasSetInterface ? HashSetType : ListType;

return Expression.New(
objectType.GetPublicInstanceConstructor(EnumerableInterfaceType),
Expand Down Expand Up @@ -151,7 +161,7 @@ public Expression GetEnumerableConversion(Expression instance, bool allowEnumera
return instance.WithToCollectionCall(ElementType);
}

return instance.WithToListLinqCall(ElementType);
return GetCopyIntoObjectConstruction(instance);
}

private static bool ValueIsNotEnumerableInterface(Expression instance)
Expand All @@ -166,7 +176,7 @@ public Type GetEmptyInstanceCreationFallbackType()
? EnumerableType.GetDictionaryConcreteType()
: IsCollection
? CollectionType
: IsHashSet
: HasSetInterface
? HashSetType
: ListType;
}
Expand Down