Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing mapping plan translation with assignments of local enum variables #171

Merged
merged 1 commit into from
Nov 4, 2019
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
58 changes: 58 additions & 0 deletions AgileMapper.UnitTests/Configuration/WhenViewingMappingPlans.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace AgileObjects.AgileMapper.UnitTests.Configuration
{
using System;
using System.Collections.ObjectModel;
using AgileMapper.Members;
using Common;
using TestClasses;
#if !NET35
Expand Down Expand Up @@ -188,5 +190,61 @@ public void ShouldIncludeUnmappableReadOnlyIntMemberDetails()
plan.ShouldContain("readonly int");
}
}

// See https://github.com/agileobjects/AgileMapper/issues/168
[Fact]
public void ShouldIncludeADataSourceFuncInvocation()
{
using (var mapper = Mapper.CreateNew())
{
Func<IMappingData<Issue168.ISomething, Issue168.TgtSomething>, Issue168.SrcEnum> getEnum =
ctxt => ctxt.Source is Issue168.SomethingB someB ? someB.MyLargeEnum : Issue168.SrcEnum.A;

mapper.WhenMapping
.From<Issue168.ISomething>().To<Issue168.TgtSomething>()
.Map(getEnum).To(tgt => tgt.MyLargeEnumg);

string mappingPlan = mapper.GetPlanFor<Issue168.ISomething>().ToANew<Issue168.TgtSomething>();

mappingPlan.ShouldNotBeNull();
mappingPlan.ShouldContain("srcEnumValue = ");
mappingPlan.ShouldContain(".Invoke(sToTsData)");
}
}

#region Helper Members

internal static class Issue168
{
public enum SrcEnum
{
A, B, C, D, E, F, G, H, I
}

public enum TgtEnum
{
A, B, C, D, E, F, G, H, I
}

public interface ISomething
{
string Name { get; }
}

public class SomethingB : ISomething
{
public string Name { get; set; }

public SrcEnum MyLargeEnum { get; set; }
}
public class TgtSomething
{
public string Name { get; set; }

public TgtEnum MyLargeEnumg { get; set; }
}
}

#endregion
}
}
15 changes: 8 additions & 7 deletions AgileMapper/DataSources/DataSourceBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,16 @@ private static void ProcessMemberAccesses(
return;
}

var numberOfInvocations = valueInfo.MultiInvocations.Count;
variables = new ParameterExpression[numberOfInvocations];
var cacheVariablesByValue = new Dictionary<Expression, Expression>(numberOfInvocations);
var valueExpressions = new Expression[numberOfInvocations + 1];
// TODO: Optimise for single multi-invocation
var multiInvocationsCount = valueInfo.MultiInvocations.Count;
variables = new ParameterExpression[multiInvocationsCount];
var cacheVariablesByValue = new Dictionary<Expression, Expression>(multiInvocationsCount);
var valueExpressions = new Expression[multiInvocationsCount + 1];

for (var i = 0; i < numberOfInvocations; i++)
for (var i = 0; i < multiInvocationsCount; i++)
{
var invocation = valueInfo.MultiInvocations[i];
var valueVariableName = invocation.Type.GetFriendlyName().ToCamelCase() + "Value";
var valueVariableName = invocation.Type.GetVariableNameInCamelCase() + "Value";
var valueVariable = Expression.Variable(invocation.Type, valueVariableName);
var valueVariableValue = invocation.Replace(cacheVariablesByValue);

Expand All @@ -91,7 +92,7 @@ private static void ProcessMemberAccesses(
valueExpressions[i] = valueVariable.AssignTo(valueVariableValue);
}

valueExpressions[numberOfInvocations] = value.Replace(cacheVariablesByValue);
valueExpressions[multiInvocationsCount] = value.Replace(cacheVariablesByValue);
value = Expression.Block(valueExpressions);
}

Expand Down
1 change: 1 addition & 0 deletions AgileMapper/Validation/EnumMappingMismatchFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ private static bool TargetMemberIsAnEnum(QualifiedMember targetMember, out Type
protected override Expression VisitBinary(BinaryExpression binary)
{
if ((binary.NodeType == ExpressionType.Assign) &&
(binary.Left.NodeType != ExpressionType.Parameter) &&
IsEnum(binary.Left.Type) &&
TryGetMatch(binary.Left, out var targetMemberData))
{
Expand Down