Skip to content

Commit c51b0e0

Browse files
authored
Merge pull request #2162 from AutoMapper/ForPathIgnore
Allow ignores on reverse map paths
2 parents 6fb62e2 + 162b8b7 commit c51b0e0

File tree

5 files changed

+62
-14
lines changed

5 files changed

+62
-14
lines changed

src/AutoMapper/Configuration/PathConfigurationExpression.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ public void MapFrom<TSourceMember>(Expression<Func<TSource, TSourceMember>> sour
2828
MapFromUntyped(sourceExpression);
2929
}
3030

31+
public void Ignore()
32+
{
33+
PathMapActions.Add(pm => pm.Ignored = true);
34+
}
35+
3136
public void MapFromUntyped(LambdaExpression sourceExpression)
3237
{
3338
_sourceExpression = sourceExpression;
@@ -39,14 +44,6 @@ public void MapFromUntyped(LambdaExpression sourceExpression)
3944

4045
public void Configure(TypeMap typeMap)
4146
{
42-
//var destMember = DestinationMember;
43-
44-
//if(destMember.DeclaringType.IsGenericType())
45-
//{
46-
// var destTypeInfo = typeMap.Profile.CreateTypeDetails(destMember.DeclaringType);
47-
// destMember = destTypeInfo.PublicReadAccessors.Single(m => m.Name == destMember.Name);
48-
//}
49-
5047
var pathMap = typeMap.FindOrCreatePathMapFor(_destinationExpression, MemberPath, typeMap);
5148

5249
Apply(pathMap);

src/AutoMapper/Execution/TypeMapPlanBuilder.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,20 +188,16 @@ private Expression CreateDestinationFunc(out bool constructorMapping)
188188
private Expression CreateAssignmentFunc(Expression destinationFunc, bool constructorMapping)
189189
{
190190
var actions = new List<Expression>();
191-
foreach(var propertyMap in _typeMap.GetPropertyMaps())
191+
foreach(var propertyMap in _typeMap.GetPropertyMaps().Where(pm => pm.CanResolveValue()))
192192
{
193-
if(!propertyMap.CanResolveValue())
194-
{
195-
continue;
196-
}
197193
var property = TryPropertyMap(propertyMap);
198194
if(constructorMapping && _typeMap.ConstructorParameterMatches(propertyMap.DestinationProperty.Name))
199195
{
200196
property = IfThen(NotEqual(_initialDestination, Constant(null)), property);
201197
}
202198
actions.Add(property);
203199
}
204-
foreach(var pathMap in _typeMap.PathMaps)
200+
foreach(var pathMap in _typeMap.PathMaps.Where(pm => !pm.Ignored))
205201
{
206202
actions.Add(HandlePath(pathMap));
207203
}

src/AutoMapper/IPathConfigurationExpression.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,10 @@ public interface IPathConfigurationExpression<TSource, out TDestination>
1818
/// <typeparam name="TSourceMember">Member type of the source member to use</typeparam>
1919
/// <param name="sourceMember">Expression referencing the source member to map against</param>
2020
void MapFrom<TSourceMember>(Expression<Func<TSource, TSourceMember>> sourceMember);
21+
22+
/// <summary>
23+
/// Ignore this member for configuration validation and skip during mapping
24+
/// </summary>
25+
void Ignore();
2126
}
2227
}

src/AutoMapper/PathMap.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ public PathMap(LambdaExpression destinationExpression, MemberPath memberPath, Ty
2121
public LambdaExpression SourceExpression { get; set; }
2222
public MemberPath MemberPath { get; }
2323
public MemberInfo DestinationMember => MemberPath.Last;
24+
public bool Ignored { get; set; }
2425
}
2526
}

src/UnitTests/ForPath.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,55 @@ public void Should_unflatten()
131131
}
132132
}
133133

134+
public class ForPathWithIgnoreShouldNotSetValue : AutoMapperSpecBase
135+
{
136+
public partial class TimesheetModel
137+
{
138+
public int ID { get; set; }
139+
public DateTime? StartDate { get; set; }
140+
public int? Contact { get; set; }
141+
public ContactModel ContactNavigation { get; set; }
142+
}
143+
144+
public class TimesheetViewModel
145+
{
146+
public int? Contact { get; set; }
147+
public DateTime? StartDate { get; set; }
148+
}
149+
150+
public class ContactModel
151+
{
152+
public int Id { get; set; }
153+
}
154+
155+
protected override MapperConfiguration Configuration { get; } = new MapperConfiguration(cfg =>
156+
{
157+
cfg.CreateMap<TimesheetModel, TimesheetViewModel>()
158+
.ForMember(d => d.Contact, o => o.MapFrom(s => s.ContactNavigation.Id))
159+
.ReverseMap()
160+
.ForPath(s => s.ContactNavigation.Id, opt => opt.Ignore());
161+
});
162+
163+
[Fact]
164+
public void Should_not_set_value()
165+
{
166+
var source = new TimesheetModel
167+
{
168+
Contact = 6,
169+
ContactNavigation = new ContactModel
170+
{
171+
Id = 5
172+
}
173+
};
174+
var dest = new TimesheetViewModel
175+
{
176+
Contact = 10
177+
};
178+
Mapper.Map(dest, source);
179+
180+
source.ContactNavigation.Id.ShouldEqual(5);
181+
}
182+
}
134183

135184
public class ForPathWithPrivateSetters : AutoMapperSpecBase
136185
{

0 commit comments

Comments
 (0)