Skip to content

Commit 0983340

Browse files
committed
Fix for: "Argument types do not match" exception when mapping a member init expression.
1 parent bdc0c9d commit 0983340

File tree

4 files changed

+64
-24
lines changed

4 files changed

+64
-24
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<PropertyGroup>
33
<Authors>Jimmy Bogard</Authors>
44
<LangVersion>latest</LangVersion>
5-
<VersionPrefix>3.1.1</VersionPrefix>
5+
<VersionPrefix>3.1.2-preview01</VersionPrefix>
66
<WarningsAsErrors>true</WarningsAsErrors>
77
<NoWarn>$(NoWarn);1701;1702;1591</NoWarn>
88
</PropertyGroup>

src/AutoMapper.Extensions.ExpressionMapping/Extensions/VisitorExtensions.cs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -67,32 +67,26 @@ public static string GetPropertyFullName(this Expression expression)
6767
}
6868
}
6969

70-
private static MemberExpression GetMemberExpression(LambdaExpression expr)
70+
private static Expression GetUnconvertedMemberExpression(this Expression expression)
7171
{
72-
MemberExpression me;
73-
switch (expr.Body.NodeType)
72+
switch (expression.NodeType)
7473
{
7574
case ExpressionType.Convert:
7675
case ExpressionType.ConvertChecked:
77-
var ue = expr.Body as UnaryExpression;
78-
me = ue?.Operand as MemberExpression;
79-
break;
76+
case ExpressionType.TypeAs:
77+
return ((UnaryExpression)expression).Operand.GetUnconvertedMemberExpression();
8078
default:
81-
me = expr.Body as MemberExpression;
82-
if (me == null)
83-
{
84-
if (expr.Body is BinaryExpression binaryExpression)
85-
{
86-
if (binaryExpression.Left is MemberExpression left)
87-
return left;
88-
if (binaryExpression.Right is MemberExpression right)
89-
return right;
90-
}
91-
}
92-
break;
79+
return expression;
9380
}
81+
}
82+
83+
public static Expression ConvertTypeIfNecessary(this Expression expression, Type memberType)
84+
{
85+
expression = expression.GetUnconvertedMemberExpression();
86+
if (memberType != expression.Type)
87+
return Expression.Convert(expression, memberType);
9488

95-
return me;
89+
return expression;
9690
}
9791

9892
/// <summary>

src/AutoMapper.Extensions.ExpressionMapping/XpressionMapperVisitor.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ protected override Expression VisitMemberInit(MemberInitExpression node)
167167

168168
private MemberBinding DoBind(PropertyMap propertyMap, Expression initial, Expression mapped)
169169
{
170+
mapped = mapped.ConvertTypeIfNecessary(propertyMap.SourceMember.GetMemberType());
170171
this.TypeMappings.AddTypeMapping(ConfigurationProvider, initial.Type, mapped.Type);
171172
return Expression.Bind(propertyMap.SourceMember, mapped);
172173
}

tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/XpressionMapperTests.cs

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ public void Map__select_method_projecting_to_model_type()
430430
}
431431

432432
[Fact]
433-
public void Map_MemberInit()
433+
public void Map_member_init()
434434
{
435435
//Arrange
436436
Expression<Func<ThingModel, ThingModel>> selection = s => new ThingModel { Car = s.Car };
@@ -442,6 +442,32 @@ public void Map_MemberInit()
442442
Assert.NotNull(selectionMapped);
443443
}
444444

445+
[Fact]
446+
public void Map_member_init_when_source_member_is_enum_and_destination_member_is_int()
447+
{
448+
//Arrange
449+
Expression<Func<ModelWithEnumMembers, ModelWithEnumMembers>> selection = m => new ModelWithEnumMembers { EnumValue = m.EnumValue };
450+
451+
//Act
452+
var selectionMapped = mapper.MapExpression<Expression<Func<EntityWithIntMembers, EntityWithIntMembers>>>(selection);
453+
454+
//Assert
455+
Assert.NotNull(selectionMapped);
456+
}
457+
458+
[Fact]
459+
public void Map_member_init_when_source_member_is_nullable_enum_and_destination_member_is_int()
460+
{
461+
//Arrange
462+
Expression<Func<ModelWithEnumMembers, ModelWithEnumMembers>> selection = m => new ModelWithEnumMembers { NullableEnumValue = m.NullableEnumValue };
463+
464+
//Act
465+
var selectionMapped = mapper.MapExpression<Expression<Func<EntityWithIntMembers, EntityWithIntMembers>>>(selection);
466+
467+
//Assert
468+
Assert.NotNull(selectionMapped);
469+
}
470+
445471
[Fact]
446472
public void Map_Constructor_NoParams()
447473
{
@@ -842,9 +868,6 @@ public void Can_map_expression_when_mapped_when_members_parent_is_a_method()
842868
[Fact]
843869
public void Can_map_expression_with_condittional_logic_while_deflattening()
844870
{
845-
/*
846-
CreateMap<TestEntity, TestDTO>()
847-
.ForMember(dst => dst.NestedClass, opt => opt.MapFrom(src => src.ConditionField == 1 ? src : default));*/
848871
Expression<Func<TestDTO, bool>> expr = x => x.NestedClass.NestedField == 1;
849872

850873
var mappedExpression = mapper.MapExpression<Expression<Func<TestEntity, bool>>>(expr);
@@ -1303,6 +1326,24 @@ public class TestDTONestedClass
13031326
public int? NestedField { get; set; }
13041327
}
13051328

1329+
public enum TestEnum
1330+
{
1331+
Prop0 = 0,
1332+
Prop1 = 1
1333+
}
1334+
1335+
public class EntityWithIntMembers
1336+
{
1337+
public int IntValue { get; set; }
1338+
public int OtherIntValue { get; set; }
1339+
}
1340+
1341+
public class ModelWithEnumMembers
1342+
{
1343+
public TestEnum EnumValue { get; set; }
1344+
public TestEnum? NullableEnumValue { get; set; }
1345+
}
1346+
13061347
public class OrganizationProfile : Profile
13071348
{
13081349
public OrganizationProfile()
@@ -1415,6 +1456,10 @@ public OrganizationProfile()
14151456

14161457
CreateMap<TestEntity, TestDTONestedClass>()
14171458
.ForMember(dst => dst.NestedField, opt => opt.MapFrom(src => (int?)src.ToBeNestedField));
1459+
1460+
CreateMap<EntityWithIntMembers, ModelWithEnumMembers>()
1461+
.ForMember(e => e.EnumValue, o => o.MapFrom(s => (TestEnum)s.IntValue))
1462+
.ForMember(e => e.NullableEnumValue, o => o.MapFrom(s => ((TestEnum)s.OtherIntValue) as TestEnum?));
14181463
}
14191464
}
14201465

0 commit comments

Comments
 (0)