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
595 changes: 593 additions & 2 deletions AgileMapper.UnitTests.Net35/AgileMapper.UnitTests.Net35.csproj

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions AgileMapper.UnitTests/AgileMapper.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@
<Compile Include="TestClasses\PaymentTypeUk.cs" />
<Compile Include="TestClasses\PaymentTypeUs.cs" />
<Compile Include="TestClasses\PublicCtorStruct.cs" />
<Compile Include="TestClasses\PublicEnumerable.cs" />
<Compile Include="TestClasses\PublicImplementation.cs" />
<Compile Include="TestClasses\PublicIndex.cs" />
<Compile Include="TestClasses\PublicSealed.cs" />
Expand Down
56 changes: 45 additions & 11 deletions AgileMapper.UnitTests/Configuration/WhenConfiguringDataSources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public void ShouldAllowConditionTypeTestsWhenMappingFromAnInterface()

// See https://github.com/agileobjects/AgileMapper/issues/111
[Fact]
public void ShouldConditionallyApplyAToTargetConfiguredSimpleTypeConstant()
public void ShouldConditionallyApplyAToTargetSimpleTypeConstant()
{
using (var mapper = Mapper.CreateNew())
{
Expand All @@ -195,7 +195,7 @@ public void ShouldConditionallyApplyAToTargetConfiguredSimpleTypeConstant()
}

[Fact]
public void ShouldConditionallyApplyAToTargetConfiguredSimpleType()
public void ShouldConditionallyApplyAToTargetSimpleType()
{
using (var mapper = Mapper.CreateNew())
{
Expand All @@ -212,7 +212,7 @@ public void ShouldConditionallyApplyAToTargetConfiguredSimpleType()
}

[Fact]
public void ShouldConditionallyApplyAToTargetConfiguredNestedSimpleTypeExpression()
public void ShouldConditionallyApplyAToTargetNestedSimpleTypeExpression()
{
using (var mapper = Mapper.CreateNew())
{
Expand All @@ -236,7 +236,7 @@ public void ShouldConditionallyApplyAToTargetConfiguredNestedSimpleTypeExpressio
}

[Fact]
public void ShouldConditionallyApplyAToTargetConfiguredSimpleTypeExpressionInAComplexTypeList()
public void ShouldConditionallyApplyAToTargetSimpleTypeExpressionToAComplexTypeListMember()
{
using (var mapper = Mapper.CreateNew())
{
Expand Down Expand Up @@ -536,7 +536,7 @@ public void ShouldApplyAConfiguredExpressionToAnArray()
.From<PublicProperty<string>>()
.To<PublicField<int[]>>()
#if NETCOREAPP2_0
.Map(ctx => ctx.Source.Value.Split(':', System.StringSplitOptions.None))
.Map(ctx => ctx.Source.Value.Split(':', StringSplitOptions.None))
#else
.Map(ctx => ctx.Source.Value.Split(':'))
#endif
Expand Down Expand Up @@ -1213,7 +1213,7 @@ public void ShouldApplyAConfiguredSourceInterfaceMember()

// See https://github.com/agileobjects/AgileMapper/issues/64
[Fact]
public void ShouldApplyAConfiguredRootSource()
public void ShouldApplyAConfiguredToTargetDataSource()
{
using (var mapper = Mapper.CreateNew())
{
Expand All @@ -1235,7 +1235,7 @@ public void ShouldApplyAConfiguredRootSource()
}

[Fact]
public void ShouldApplyANestedOverwriteConfiguredRootSource()
public void ShouldApplyANestedOverwriteConfiguredToTargetDataSource()
{
using (var mapper = Mapper.CreateNew())
{
Expand Down Expand Up @@ -1395,7 +1395,7 @@ public void ShouldApplyAConfiguredRootSourceToANestedMember()
}

[Fact]
public void ShouldApplyAConfiguredRootSourceToAnEnumerableElement()
public void ShouldApplyAToTargetComplexTypeToAComplexTypeEnumerableElement()
{
using (var mapper = Mapper.CreateNew())
{
Expand Down Expand Up @@ -1426,7 +1426,7 @@ public void ShouldApplyAConfiguredRootSourceToAnEnumerableElement()
}

[Fact]
public void ShouldApplyAConfiguredEnumerableRootSource()
public void ShouldApplyAToTargetComplexTypeEnumerable()
{
using (var mapper = Mapper.CreateNew())
{
Expand Down Expand Up @@ -1463,7 +1463,7 @@ public void ShouldApplyAConfiguredEnumerableRootSource()
}

[Fact]
public void ShouldApplyMultipleConfiguredComplexTypeRootSources()
public void ShouldApplyMultipleToTargetComplexTypes()
{
using (var mapper = Mapper.CreateNew())
{
Expand All @@ -1490,7 +1490,7 @@ public void ShouldApplyMultipleConfiguredComplexTypeRootSources()
}

[Fact]
public void ShouldApplyMultipleConfiguredEnumerableRootSources()
public void ShouldApplyMultipleToTargetSimpleTypeEnumerables()
{
using (var mapper = Mapper.CreateNew())
{
Expand Down Expand Up @@ -1619,6 +1619,40 @@ public void ShouldHandleDeepNestedRuntimeTypedMembersWithACachedMappingPlan()
}
}

[Fact]
public void ShouldApplyAToTargetSimpleTypeToANestedComplexTypeMember()
{
using (var mapper = Mapper.CreateNew())
{
mapper.WhenMapping
.From<string>().To<PublicEnumerable<int>>()
.Map(ctx => PublicEnumerable<int>.Parse(ctx.Source)).ToTarget();

mapper.GetPlanFor<PublicField<string>>().ToANew<PublicField<PublicEnumerable<int>>>();

var source = new PublicField<string> { Value = "1,2,3" };
var result = mapper.Map(source).ToANew<PublicField<PublicEnumerable<int>>>();

result.ShouldNotBeNull();
result.Value.ShouldNotBeNull();
result.Value.ShouldBe(1, 2, 3);
}
}

[Fact]
public void ShouldConditionallyApplyAToTargetSimpleTypeToANestedComplexTypeMember()
{
using (var mapper = Mapper.CreateNew())
{
mapper.WhenMapping
.From<string>().To<PublicEnumerable<int>>()
.If(cxt => cxt.Source.Contains(','))
.Map(ctx => PublicEnumerable<int>.Parse(ctx.Source)).ToTarget();

mapper.GetPlanFor<PublicField<string>>().ToANew<PublicField<PublicEnumerable<int>>>();
}
}

#region Helper Classes

internal class IdTester
Expand Down
2 changes: 1 addition & 1 deletion AgileMapper.UnitTests/Members/WhenFindingDataSources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ private IQualifiedMember GetMatchingSourceMember<TSource, TTarget>(
var childMapperData = new ChildMemberMapperData(targetMember, rootMapperData);
var childMappingContext = rootMappingData.GetChildMappingData(childMapperData);

return SourceMemberMatcher.GetMatchFor(childMappingContext, out _);
return SourceMemberMatcher.GetMatchFor(childMappingContext).SourceMember;
}

#region Helper Classes
Expand Down
34 changes: 34 additions & 0 deletions AgileMapper.UnitTests/TestClasses/PublicEnumerable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace AgileObjects.AgileMapper.UnitTests.TestClasses
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

internal class PublicEnumerable<T> : IEnumerable<T>
{
private readonly List<T> _items;

public PublicEnumerable()
: this(new List<T>())
{
}

private PublicEnumerable(List<T> items)
{
_items = items;
}

public static PublicEnumerable<T> Parse(string values)
{
return new PublicEnumerable<T>(values
.Split(',')
.Select(v => (T)Convert.ChangeType(v, typeof(T)))
.ToList());
}

public IEnumerator<T> GetEnumerator() => _items.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,16 @@ private void ThrowIfRedundantSourceMember(ConfiguredLambdaInfo valueLambdaInfo,

var targetMemberMapperData = new ChildMemberMapperData(targetMember, mappingData.MapperData);
var targetMemberMappingData = mappingData.GetChildMappingData(targetMemberMapperData);
var bestMatchingSourceMember = SourceMemberMatcher.GetMatchFor(targetMemberMappingData, out _);
var bestSourceMemberMatch = SourceMemberMatcher.GetMatchFor(targetMemberMappingData);

if (bestMatchingSourceMember == null)
if (!bestSourceMemberMatch.IsUseable)
{
return;
}

var sourceMember = sourceMemberLambda.ToSourceMember(MapperContext);

if (!bestMatchingSourceMember.Matches(sourceMember))
if (!bestSourceMemberMatch.SourceMember.Matches(sourceMember))
{
return;
}
Expand Down
4 changes: 0 additions & 4 deletions AgileMapper/Configuration/Inline/InlineMapperContextSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
#if NET35
using System.Linq;
#endif
using System.Linq.Expressions;
using Api.Configuration;
using Api.Configuration.Projection;
using Caching;
using Extensions;
#if NET35
using Extensions.Internal;
#endif
Expand Down
24 changes: 14 additions & 10 deletions AgileMapper/Configuration/ParametersSwapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ namespace AgileObjects.AgileMapper.Configuration
using System;
using System.Collections.Generic;
using System.Linq;
using Extensions;
using Extensions.Internal;
using Members;
using NetStandardPolyfills;
using ObjectPopulation;
#if NET35
using Microsoft.Scripting.Ast;
#else
using System.Linq.Expressions;
#endif
using Extensions;
using Extensions.Internal;
using Members;
using NetStandardPolyfills;
using ObjectPopulation;
using static Members.Member;

internal class ParametersSwapper
Expand Down Expand Up @@ -170,7 +170,7 @@ private static Expression ReplaceParameters(

private static MappingContextInfo GetAppropriateMappingContext(SwapArgs swapArgs)
{
if (swapArgs.ContextTypes.All(t => t.IsSimple()))
if (swapArgs.SourceType.IsSimple())
{
return GetSimpleTypesMappingContextInfo(swapArgs);
}
Expand Down Expand Up @@ -298,8 +298,8 @@ public MappingContextInfo(SwapArgs swapArgs, Expression contextAccess)
: this(
swapArgs,
contextAccess,
GetValueAccess(swapArgs.GetSourceAccess(contextAccess), swapArgs.ContextTypes[0]),
GetValueAccess(swapArgs.GetTargetAccess(contextAccess), swapArgs.ContextTypes[1]))
GetValueAccess(swapArgs.GetSourceAccess(contextAccess), swapArgs.SourceType),
GetValueAccess(swapArgs.GetTargetAccess(contextAccess), swapArgs.TargetType))
{
}

Expand Down Expand Up @@ -370,6 +370,10 @@ public SwapArgs(

public Type[] ContextTypes { get; }

public Type SourceType => ContextTypes[0];

public Type TargetType => ContextTypes[1];

public IMemberMapperData MapperData { get; }

public Func<IMemberMapperData, Expression, Type, Expression> TargetValueFactory { get; }
Expand All @@ -386,10 +390,10 @@ public Expression GetTypedContextAccess(Expression contextAccess)
=> MapperData.GetTypedContextAccess(contextAccess, ContextTypes);

public Expression GetSourceAccess(Expression contextAccess)
=> MapperData.GetSourceAccess(contextAccess, ContextTypes[0]);
=> MapperData.GetSourceAccess(contextAccess, SourceType);

public Expression GetTargetAccess(Expression contextAccess)
=> TargetValueFactory.Invoke(MapperData, contextAccess, ContextTypes[1]);
=> TargetValueFactory.Invoke(MapperData, contextAccess, TargetType);
}

#endregion
Expand Down
2 changes: 1 addition & 1 deletion AgileMapper/DataSources/AdHocDataSource.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
namespace AgileObjects.AgileMapper.DataSources
{
using System.Collections.Generic;
using Members;
#if NET35
using Microsoft.Scripting.Ast;
#else
using System.Linq.Expressions;
#endif
using Members;

internal class AdHocDataSource : DataSourceBase
{
Expand Down
13 changes: 5 additions & 8 deletions AgileMapper/DataSources/Finders/DataSourceFindContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,15 @@ public DataSourceFindContext(IChildMemberMappingData childMappingData)
GetConfiguredDataSources(originalChildMapperData));
}

private IList<IConfiguredDataSource> GetConfiguredDataSources(IMemberMapperData mapperData)
{
return MapperData
.MapperContext
.UserConfigurations
.GetDataSources(mapperData);
}
private IList<IConfiguredDataSource> GetConfiguredDataSources(IMemberMapperData mapperData)
=> MapperContext.UserConfigurations.GetDataSources(mapperData);

public IChildMemberMappingData ChildMappingData { get; }

public IMemberMapperData MapperData => ChildMappingData.MapperData;

public MapperContext MapperContext => MapperData.MapperContext;

public int DataSourceIndex { get; set; }

public bool StopFind { get; set; }
Expand All @@ -59,7 +56,7 @@ public IDataSource GetFinalDataSource(IDataSource foundDataSource, IChildMemberM
return new ComplexTypeMappingDataSource(foundDataSource, DataSourceIndex, mappingData);
}

if (childTargetMember.IsEnumerable)
if (childTargetMember.IsEnumerable && foundDataSource.SourceMember.IsEnumerable)
{
return new EnumerableMappingDataSource(foundDataSource, DataSourceIndex, mappingData);
}
Expand Down
7 changes: 4 additions & 3 deletions AgileMapper/DataSources/Finders/MetaMemberDataSourceFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,16 +214,17 @@ private static bool TryGetMetaMember(

var memberMappingData = currentMappingData.GetChildMappingData(childMemberMapperData);

currentSourceMember = SourceMemberMatcher.GetMatchFor(
var currentSourceMemberMatch = SourceMemberMatcher.GetMatchFor(
memberMappingData,
out _,
searchParentContexts: false);

if (currentSourceMember == null)
if (!currentSourceMemberMatch.IsUseable)
{
return false;
}

currentSourceMember = currentSourceMemberMatch.SourceMember;

currentMemberPart = new SourceMemberMetaMemberPart(
currentSourceMember,
currentMapperData,
Expand Down
Loading