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
11 changes: 11 additions & 0 deletions src/AutoMapper/Configuration/MemberConfigurationExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,17 @@ public void PreCondition(Func<ResolutionContext, bool> condition)
});
}

public void PreCondition(Func<TSource, ResolutionContext, bool> condition)
{
PropertyMapActions.Add(pm =>
{
Expression<Func<TSource, ResolutionContext, bool>> expr =
(src, ctxt) => condition(src, ctxt);

pm.PreCondition = expr;
});
}

public void ExplicitExpansion()
{
PropertyMapActions.Add(pm => pm.ExplicitExpansion = true);
Expand Down
6 changes: 6 additions & 0 deletions src/AutoMapper/IMemberConfigurationExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ void ResolveUsing<TValueResolver, TSourceMember>(string sourceMemberName)
/// <param name="condition">Condition to evaluate using the current resolution context</param>
void PreCondition(Func<ResolutionContext, bool> condition);

/// <summary>
/// Conditionally map this member, evaluated before accessing the source value
/// </summary>
/// <param name="condition">Condition to evaluate using the source object and the current resolution context</param>
void PreCondition(Func<TSource, ResolutionContext, bool> condition);

/// <summary>
/// Ignore this member for LINQ projections unless explicitly expanded during projection
/// </summary>
Expand Down
69 changes: 62 additions & 7 deletions src/UnitTests/Bug/ConditionBug.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,42 +199,97 @@ public void Should_not_map_value_when_not_null()
namespace SourceValueExceptionConditionPropertyBug
{
using System;
using System.Collections.Generic;
using Shouldly;
using Xunit;

public enum Property
{
Value1 = 0,
Value2 = 1,
Value3 = 2
}

public class Source
{
public bool Accessed = false;
public int Value
public Dictionary<Property, bool> Accessed = new Dictionary<Property, bool>
{
{Property.Value1, false},
{Property.Value2, false},
{Property.Value3, false}
};

public int Value1
{
get
{
Accessed = true;
Accessed[Property.Value1] = true;
return 5;
}
}

public int Value2
{
get
{
Accessed[Property.Value2] = true;
return 10;
}
}

public int Value3
{
get
{
Accessed[Property.Value3] = true;
return 15;
}
}
}

public class Dest
{
public int Value { get; set; }
public int Value1 { get; set; }

public int Value2 { get; set; }

public int Value3 { get; set; }
}

public class ConditionTests : NonValidatingSpecBase
{
protected override MapperConfiguration Configuration { get; } = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Source, Dest>()
.ForMember(d => d.Value, opt => opt.PreCondition((ResolutionContext rc) => false));
.ForMember(d => d.Value1, opt => opt.PreCondition((Source src) => false))
.ForMember(d => d.Value2, opt => opt.PreCondition((ResolutionContext rc) => false))
.ForMember(d => d.Value3, opt => opt.PreCondition((src, rc) => false));
});

[Fact]
public void Should_not_map()
public void Should_not_map_when_precondition_with_source_parameter_is_false()
{
var source = new Source();
Mapper.Map<Source, Dest>(source);
source.Accessed.ShouldBeFalse();
source.Accessed[Property.Value1].ShouldBeFalse();
}

[Fact]
public void Should_not_map_when_precondition_with_resolutioncontext_parameter_is_false()
{
var source = new Source();
Mapper.Map<Source, Dest>(source);
source.Accessed[Property.Value2].ShouldBeFalse();
}

[Fact]
public void Should_not_map_when_precondition_with_source_and_resolutioncontext_parameters_is_false()
{
var source = new Source();
Mapper.Map<Source, Dest>(source);
source.Accessed[Property.Value3].ShouldBeFalse();
}

}
}

Expand Down