Skip to content

Commit

Permalink
by default, inline only one level deep
Browse files Browse the repository at this point in the history
  • Loading branch information
lbargaoanu committed Aug 14, 2017
1 parent 0244894 commit 9fef24c
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 64 deletions.
6 changes: 6 additions & 0 deletions src/AutoMapper/AdvancedConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public class AdvancedConfiguration

public bool AllowAdditiveTypeMapCreation { get; set; }

/// <summary>
/// How many levels deep should AutoMapper try to inline the execution plan for child classes.
/// See <a href="https://github.com/AutoMapper/AutoMapper/wiki/Understanding-your-mapping">the wiki</a> for details.
/// </summary>
public int MaxExecutionPlanDepth { get; set; } = 1;

internal Validator[] GetValidators() => _validators.ToArray();
}
}
23 changes: 14 additions & 9 deletions src/AutoMapper/Execution/TypeMapPlanBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,21 +80,26 @@ private void CheckForCycles(Stack<TypeMap> typeMapsPath)
typeMapsPath = new Stack<TypeMap>();
}
typeMapsPath.Push(_typeMap);
var propertyTypeMaps =
(from propertyTypeMap in
(from pm in _typeMap.GetPropertyMaps() where pm.CanResolveValue() select ResolvePropertyTypeMap(pm))
var properties =
from pm in _typeMap.GetPropertyMaps() where pm.CanResolveValue()
let propertyTypeMap = ResolvePropertyTypeMap(pm)
where propertyTypeMap != null && !propertyTypeMap.PreserveReferences
select propertyTypeMap).Distinct();
foreach (var propertyTypeMap in propertyTypeMaps)
select new { PropertyTypeMap = propertyTypeMap, PropertyMap = pm };
foreach(var property in properties)
{
if(typeMapsPath.Contains(propertyTypeMap))
if(typeMapsPath.Count % _configurationProvider.MaxExecutionPlanDepth == 0)
{
property.PropertyMap.Inline = false;
Debug.WriteLine($"Resetting Inline: {property.PropertyMap.DestinationProperty} in {_typeMap.SourceType} - {_typeMap.DestinationType}");
}
if(typeMapsPath.Contains(property.PropertyTypeMap))
{
Debug.WriteLine($"Setting PreserveReferences: {_typeMap.SourceType} - {_typeMap.DestinationType} => {propertyTypeMap.SourceType} - {propertyTypeMap.DestinationType}");
propertyTypeMap.PreserveReferences = true;
Debug.WriteLine($"Setting PreserveReferences: {_typeMap.SourceType} - {_typeMap.DestinationType} => {property.PropertyTypeMap.SourceType} - {property.PropertyTypeMap.DestinationType}");
property.PropertyTypeMap.PreserveReferences = true;
}
else
{
propertyTypeMap.Seal(_configurationProvider, typeMapsPath);
property.PropertyTypeMap.Seal(_configurationProvider, typeMapsPath);
}
}
typeMapsPath.Pop();
Expand Down
2 changes: 2 additions & 0 deletions src/AutoMapper/IConfigurationProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ public interface IConfigurationProvider
/// </summary>
bool EnableNullPropagationForQueryMapping { get; }

int MaxExecutionPlanDepth { get; }

IExpressionBuilder ExpressionBuilder { get; }

/// <summary>
Expand Down
5 changes: 4 additions & 1 deletion src/AutoMapper/MapperConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public MapperConfiguration(MapperConfigurationExpression configurationExpression

ServiceCtor = configurationExpression.ServiceCtor;
EnableNullPropagationForQueryMapping = configurationExpression.EnableNullPropagationForQueryMapping ?? false;
MaxExecutionPlanDepth = configurationExpression.Advanced.MaxExecutionPlanDepth + 1;

Configuration = new ProfileMap(configurationExpression);
Profiles = new[] { Configuration }.Concat(configurationExpression.Profiles.Select(p => new ProfileMap(p, configurationExpression))).ToArray();
Expand Down Expand Up @@ -69,7 +70,9 @@ public void Validate(ValidationContext context)

public Func<Type, object> ServiceCtor { get; }

public bool EnableNullPropagationForQueryMapping { get; }
public bool EnableNullPropagationForQueryMapping { get; }

public int MaxExecutionPlanDepth { get; }

private ProfileMap Configuration { get; }

Expand Down
54 changes: 27 additions & 27 deletions src/UnitTests/Bug/MapAtRuntime/MapAtRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,33 @@ public class MapAtRuntime : AutoMapperSpecBase
{
protected override MapperConfiguration Configuration => new MapperConfiguration(cfg =>
{
cfg.CreateMap<Entity1, EntityDTO1>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity2, EntityDTO2>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity3, EntityDTO3>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity4, EntityDTO4>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity5, EntityDTO5>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity6, EntityDTO6>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity7, EntityDTO7>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity8, EntityDTO8>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity9, EntityDTO9>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity10, EntityDTO10>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity11, EntityDTO11>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity12, EntityDTO12>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity13, EntityDTO13>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity14, EntityDTO14>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity15, EntityDTO15>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity16, EntityDTO16>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity17, EntityDTO17>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity18, EntityDTO18>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity19, EntityDTO19>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity20, EntityDTO20>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity21, EntityDTO21>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity22, EntityDTO22>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity23, EntityDTO23>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity24, EntityDTO24>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity25, EntityDTO25>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity26, EntityDTO26>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.ForAllPropertyMaps(p => !p.SourceType.IsValueType(), (pm, o) => o.MapAtRuntime());
cfg.CreateMap<Entity1, EntityDTO1>().ReverseMap();
cfg.CreateMap<Entity2, EntityDTO2>().ReverseMap();
cfg.CreateMap<Entity3, EntityDTO3>().ReverseMap();
cfg.CreateMap<Entity4, EntityDTO4>().ReverseMap();
cfg.CreateMap<Entity5, EntityDTO5>().ReverseMap();
cfg.CreateMap<Entity6, EntityDTO6>().ReverseMap();
cfg.CreateMap<Entity7, EntityDTO7>().ReverseMap();
cfg.CreateMap<Entity8, EntityDTO8>().ReverseMap();
cfg.CreateMap<Entity9, EntityDTO9>().ReverseMap();
cfg.CreateMap<Entity10, EntityDTO10>().ReverseMap();
cfg.CreateMap<Entity11, EntityDTO11>().ReverseMap();
cfg.CreateMap<Entity12, EntityDTO12>().ReverseMap();
cfg.CreateMap<Entity13, EntityDTO13>().ReverseMap();
cfg.CreateMap<Entity14, EntityDTO14>().ReverseMap();
cfg.CreateMap<Entity15, EntityDTO15>().ReverseMap();
cfg.CreateMap<Entity16, EntityDTO16>().ReverseMap();
cfg.CreateMap<Entity17, EntityDTO17>().ReverseMap();
cfg.CreateMap<Entity18, EntityDTO18>().ReverseMap();
cfg.CreateMap<Entity19, EntityDTO19>().ReverseMap();
cfg.CreateMap<Entity20, EntityDTO20>().ReverseMap();
cfg.CreateMap<Entity21, EntityDTO21>().ReverseMap();
cfg.CreateMap<Entity22, EntityDTO22>().ReverseMap();
cfg.CreateMap<Entity23, EntityDTO23>().ReverseMap();
cfg.CreateMap<Entity24, EntityDTO24>().ReverseMap();
cfg.CreateMap<Entity25, EntityDTO25>().ReverseMap();
cfg.CreateMap<Entity26, EntityDTO26>().ReverseMap();
//cfg.ForAllPropertyMaps(p => !p.SourceType.IsValueType(), (pm, o) => o.MapAtRuntime());
});

public class Initialize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,33 @@ public class MapAtRuntimeWithCollections : AutoMapperSpecBase
{
protected override MapperConfiguration Configuration => new MapperConfiguration(cfg =>
{
cfg.CreateMap<Entity1, EntityDTO1>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity2, EntityDTO2>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity3, EntityDTO3>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity4, EntityDTO4>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity5, EntityDTO5>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity6, EntityDTO6>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity7, EntityDTO7>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity8, EntityDTO8>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity9, EntityDTO9>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity10, EntityDTO10>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity11, EntityDTO11>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity12, EntityDTO12>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity13, EntityDTO13>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity14, EntityDTO14>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity15, EntityDTO15>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity16, EntityDTO16>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity17, EntityDTO17>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity18, EntityDTO18>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity19, EntityDTO19>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity20, EntityDTO20>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity21, EntityDTO21>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity22, EntityDTO22>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity23, EntityDTO23>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity24, EntityDTO24>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity25, EntityDTO25>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.CreateMap<Entity26, EntityDTO26>().PreserveReferences().ReverseMap().PreserveReferences();
cfg.ForAllPropertyMaps(p => !p.SourceType.IsValueType(), (pm, o) => o.MapAtRuntime());
cfg.CreateMap<Entity1, EntityDTO1>().ReverseMap();
cfg.CreateMap<Entity2, EntityDTO2>().ReverseMap();
cfg.CreateMap<Entity3, EntityDTO3>().ReverseMap();
cfg.CreateMap<Entity4, EntityDTO4>().ReverseMap();
cfg.CreateMap<Entity5, EntityDTO5>().ReverseMap();
cfg.CreateMap<Entity6, EntityDTO6>().ReverseMap();
cfg.CreateMap<Entity7, EntityDTO7>().ReverseMap();
cfg.CreateMap<Entity8, EntityDTO8>().ReverseMap();
cfg.CreateMap<Entity9, EntityDTO9>().ReverseMap();
cfg.CreateMap<Entity10, EntityDTO10>().ReverseMap();
cfg.CreateMap<Entity11, EntityDTO11>().ReverseMap();
cfg.CreateMap<Entity12, EntityDTO12>().ReverseMap();
cfg.CreateMap<Entity13, EntityDTO13>().ReverseMap();
cfg.CreateMap<Entity14, EntityDTO14>().ReverseMap();
cfg.CreateMap<Entity15, EntityDTO15>().ReverseMap();
cfg.CreateMap<Entity16, EntityDTO16>().ReverseMap();
cfg.CreateMap<Entity17, EntityDTO17>().ReverseMap();
cfg.CreateMap<Entity18, EntityDTO18>().ReverseMap();
cfg.CreateMap<Entity19, EntityDTO19>().ReverseMap();
cfg.CreateMap<Entity20, EntityDTO20>().ReverseMap();
cfg.CreateMap<Entity21, EntityDTO21>().ReverseMap();
cfg.CreateMap<Entity22, EntityDTO22>().ReverseMap();
cfg.CreateMap<Entity23, EntityDTO23>().ReverseMap();
cfg.CreateMap<Entity24, EntityDTO24>().ReverseMap();
cfg.CreateMap<Entity25, EntityDTO25>().ReverseMap();
cfg.CreateMap<Entity26, EntityDTO26>().ReverseMap();
//cfg.ForAllPropertyMaps(p => !p.SourceType.IsValueType(), (pm, o) => o.MapAtRuntime());
});

public class Initialize
Expand Down
109 changes: 109 additions & 0 deletions src/UnitTests/MaxExecutionPlanDepth.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using AutoMapper;
using System;
using Xunit;
using Shouldly;

namespace AutoMapper.UnitTests
{
public class MaxExecutionPlanDepth
{
class Source
{
public Source1 Inner { get; set; }
}

class Source1
{
public Source2 Inner { get; set; }
}

class Source2
{
public Source3 Inner { get; set; }
}

class Source3
{
public Source4 Inner { get; set; }
}

class Source4
{
public Source5 Inner { get; set; }
}

class Source5
{
public Source6 Inner { get; set; }
}

class Source6
{
public int Value { get; set; }
}

class Destination
{
public Destination1 Inner { get; set; }
}

class Destination1
{
public Destination2 Inner { get; set; }
}

class Destination2
{
public Destination3 Inner { get; set; }
}

class Destination3
{
public Destination4 Inner { get; set; }
}

class Destination4
{
public Destination5 Inner { get; set; }
}

class Destination5
{
public Destination6 Inner { get; set; }
}

class Destination6
{
public int Value { get; set; }
}

[Fact]
public void Should_set_inline_accordingly()
{
var configuration = new MapperConfiguration(cfg =>
{
cfg.Advanced.MaxExecutionPlanDepth = 2;
cfg.CreateMap<Source, Destination>();
cfg.CreateMap<Source1, Destination1>();
cfg.CreateMap<Source2, Destination2>();
cfg.CreateMap<Source3, Destination3>();
cfg.CreateMap<Source4, Destination4>();
cfg.CreateMap<Source5, Destination5>();
cfg.CreateMap<Source6, Destination6>();
});
TypeMap map;
map = configuration.FindTypeMapFor<Source, Destination>();
map.GetPropertyMaps()[0].Inline.ShouldBeTrue();
map = configuration.FindTypeMapFor<Source1, Destination1>();
map.GetPropertyMaps()[0].Inline.ShouldBeTrue();
map = configuration.FindTypeMapFor<Source2, Destination2>();
map.GetPropertyMaps()[0].Inline.ShouldBeFalse();
map = configuration.FindTypeMapFor<Source3, Destination3>();
map.GetPropertyMaps()[0].Inline.ShouldBeTrue();
map = configuration.FindTypeMapFor<Source4, Destination4>();
map.GetPropertyMaps()[0].Inline.ShouldBeTrue();
map = configuration.FindTypeMapFor<Source5, Destination5>();
map.GetPropertyMaps()[0].Inline.ShouldBeFalse();
}
}
}

0 comments on commit 9fef24c

Please sign in to comment.