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
5 changes: 1 addition & 4 deletions src/AutoMapper/Configuration/MappingExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
26 changes: 20 additions & 6 deletions src/AutoMapper/Configuration/MemberConfigurationExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ namespace AutoMapper.Configuration

public class MemberConfigurationExpression<TSource, TDestination, TMember> : IMemberConfigurationExpression<TSource, TDestination, TMember>, IPropertyMapConfiguration
{
private LambdaExpression _sourceMember;
private LambdaExpression _sourceExpression;
private MemberInfo _sourceMember;
private readonly Type _sourceType;
protected List<Action<PropertyMap>> PropertyMapActions { get; } = new List<Action<PropertyMap>>();

Expand Down Expand Up @@ -116,13 +117,13 @@ public void MapFrom<TSourceMember>(Expression<Func<TSource, TSourceMember>> 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));
}

Expand Down Expand Up @@ -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<TDestination, TSource, object>.Create(_sourceMember, GetDestinationExpression());
public IPropertyMapConfiguration Reverse()
{
var destinationType = DestinationMember.DeclaringType;
if (_sourceMember != null)
{
var reversedMemberConfiguration = new MemberConfigurationExpression<TDestination, TSource, object>(_sourceMember, destinationType);
reversedMemberConfiguration.MapFrom(DestinationMember.Name);
return reversedMemberConfiguration;
}
if (destinationType.IsGenericTypeDefinition) // .ForMember("InnerSource", o => o.MapFrom(s => s))
{
return null;
}
return PathConfigurationExpression<TDestination, TSource, object>.Create(_sourceExpression, GetDestinationExpression());
}

public void DontUseDestinationValue() => SetUseDestinationValue(false);
}
Expand Down
59 changes: 59 additions & 0 deletions src/UnitTests/ReverseMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Source, Destination>()
.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<Source>(destination);
source.Value.ShouldBe(1337);
}
}

public class ReverseDefaultFlatteningWithIgnoreMember : AutoMapperSpecBase
{
public class Order
Expand Down Expand Up @@ -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<T>
{
public T Value { get; set; }
public string StringValue { get; set; }
}
public class Destination<T>
{
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<int> destination = new Destination<int> { Value2 = 1337, StringValue2 = "StringValue2" };
Source<int> source = Mapper.Map<Destination<int>, Source<int>>(destination);
source.Value.ShouldBe(1337);
source.StringValue.ShouldBe("StringValue2");
}
}
}