diff --git a/src/AutoMapper/Configuration/MappingExpression.cs b/src/AutoMapper/Configuration/MappingExpression.cs index 33a4a38c76..2e41337238 100644 --- a/src/AutoMapper/Configuration/MappingExpression.cs +++ b/src/AutoMapper/Configuration/MappingExpression.cs @@ -18,10 +18,7 @@ public IMappingExpression ReverseMap() { var reversedTypes = new TypePair(Types.DestinationType, Types.SourceType); var reverseMap = new MappingExpression(reversedTypes, MemberList.None); - if(!reversedTypes.IsGenericTypeDefinition) - { - reverseMap.MemberConfigurations.AddRange(MemberConfigurations.Select(m => m.Reverse()).Where(m => m != null)); - } + reverseMap.MemberConfigurations.AddRange(MemberConfigurations.Select(m => m.Reverse()).Where(m => m != null)); ReverseMapExpression = reverseMap; reverseMap.IncludeMembers(MapToSourceMembers().Select(m => m.DestinationMember.Name).ToArray()); foreach(var includedMemberName in IncludedMembersNames) diff --git a/src/AutoMapper/Configuration/MemberConfigurationExpression.cs b/src/AutoMapper/Configuration/MemberConfigurationExpression.cs index b1a590bb0a..3c19113b62 100644 --- a/src/AutoMapper/Configuration/MemberConfigurationExpression.cs +++ b/src/AutoMapper/Configuration/MemberConfigurationExpression.cs @@ -10,7 +10,8 @@ namespace AutoMapper.Configuration public class MemberConfigurationExpression : IMemberConfigurationExpression, IPropertyMapConfiguration { - private LambdaExpression _sourceMember; + private LambdaExpression _sourceExpression; + private MemberInfo _sourceMember; private readonly Type _sourceType; protected List> PropertyMapActions { get; } = new List>(); @@ -116,13 +117,13 @@ public void MapFrom(Expression> mapE internal void MapFromUntyped(LambdaExpression sourceExpression) { - _sourceMember = sourceExpression; + _sourceExpression = sourceExpression; PropertyMapActions.Add(pm => pm.MapFrom(sourceExpression)); } public void MapFrom(string sourceMemberName) { - _sourceType.GetFieldOrProperty(sourceMemberName); + _sourceMember = _sourceType.GetFieldOrProperty(sourceMemberName); PropertyMapActions.Add(pm => pm.MapFrom(sourceMemberName)); } @@ -337,11 +338,24 @@ private void Apply(PropertyMap propertyMap) propertyMap.CheckMappedReadonly(); } - public LambdaExpression SourceExpression => _sourceMember; + public LambdaExpression SourceExpression => _sourceExpression; public LambdaExpression GetDestinationExpression() => MemberAccessLambda(DestinationMember); - public IPropertyMapConfiguration Reverse() => - PathConfigurationExpression.Create(_sourceMember, GetDestinationExpression()); + public IPropertyMapConfiguration Reverse() + { + var destinationType = DestinationMember.DeclaringType; + if (_sourceMember != null) + { + var reversedMemberConfiguration = new MemberConfigurationExpression(_sourceMember, destinationType); + reversedMemberConfiguration.MapFrom(DestinationMember.Name); + return reversedMemberConfiguration; + } + if (destinationType.IsGenericTypeDefinition) // .ForMember("InnerSource", o => o.MapFrom(s => s)) + { + return null; + } + return PathConfigurationExpression.Create(_sourceExpression, GetDestinationExpression()); + } public void DontUseDestinationValue() => SetUseDestinationValue(false); } diff --git a/src/UnitTests/ReverseMapping.cs b/src/UnitTests/ReverseMapping.cs index c2dd31bf0f..72fe4a4686 100644 --- a/src/UnitTests/ReverseMapping.cs +++ b/src/UnitTests/ReverseMapping.cs @@ -202,6 +202,34 @@ public void Should_unflatten() } } + public class ReverseMapFromSourceMemberName : AutoMapperSpecBase + { + public class Source + { + public int Value { get; set; } + } + + public class Destination + { + public int Value2 { get; set; } + } + + protected override MapperConfiguration Configuration => new MapperConfiguration(cfg => + { + cfg.CreateMap() + .ForMember(d => d.Value2, o => o.MapFrom("Value")) + .ReverseMap(); + }); + + [Fact] + public void Should_reverse_map_ok() + { + Destination destination = new Destination { Value2 = 1337 }; + Source source = Mapper.Map(destination); + source.Value.ShouldBe(1337); + } + } + public class ReverseDefaultFlatteningWithIgnoreMember : AutoMapperSpecBase { public class Order @@ -594,4 +622,35 @@ public void Should_create_a_map_with_the_reverse_items() _source.Value.ShouldBe(10); } } + + public class When_reverse_mapping_open_generics_with_MapFrom : AutoMapperSpecBase + { + public class Source + { + public T Value { get; set; } + public string StringValue { get; set; } + } + public class Destination + { + public T Value2 { get; set; } + public string StringValue2 { get; set; } + } + + protected override MapperConfiguration Configuration { get; } = new MapperConfiguration(cfg => + { + cfg.CreateMap(typeof(Source<>), typeof(Destination<>)) + .ForMember("Value2", o => o.MapFrom("Value")) + .ForMember("StringValue2", o => o.MapFrom("StringValue")) + .ReverseMap(); + }); + + [Fact] + public void Should_reverse_map_ok() + { + Destination destination = new Destination { Value2 = 1337, StringValue2 = "StringValue2" }; + Source source = Mapper.Map, Source>(destination); + source.Value.ShouldBe(1337); + source.StringValue.ShouldBe("StringValue2"); + } + } } \ No newline at end of file