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
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,33 @@ public void ShouldApplyMapperConfigurationsInOrder()
}
}

// See https://github.com/agileobjects/AgileMapper/issues/91
[Fact]
public void ShouldApplyMapperConfigurationsInOrderAutomatically()
{
var values = new List<int> { 1, 2, 3 };
var provider = new StubServiceProvider(values);

var grandParent = new GrandParent
{
DatChild = new Parent { MyChild = new Child() }
};

using (var mapper = Mapper.CreateNew())
{
mapper.WhenMapping
.UseServiceProvider(provider)
.UseConfigurations
.From<GrandParentMapperConfiguration>();

var result = mapper.Map(grandParent).ToANew<GrandParentDto>();

result.MyChild.ShouldNotBeNull();
result.MyChild.MyChild.ShouldNotBeNull();
result.MyChild.MyChild.IsMyCountGtrZero.ShouldBeTrue();
}
}

#region Helper Classes

public class PfiToPfsMapperConfiguration : MapperConfiguration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,20 @@ public void ShouldErrorIfDuplicateConfigurationAdded()
}

[Fact]
public void ShouldErrorIfDependentConfigurationAddedBeforeDependedOnConfiguration()
public void ShouldErrorIfRedundantConfigurationAdded()
{
var configEx = Should.Throw<MappingConfigurationException>(() =>
{
using (var mapper = Mapper.CreateNew())
{
mapper.WhenMapping.UseConfigurations
.From<WhenApplyingMapperConfigurations.ParentMapperConfiguration>();
.From<WhenApplyingMapperConfigurations.ParentMapperConfiguration>()
.From<WhenApplyingMapperConfigurations.ChildMapperConfiguration>();
}
});

configEx.Message.ShouldContain("ParentMapperConfiguration");
configEx.Message.ShouldContain("ChildMapperConfiguration");
configEx.Message.ShouldContain("already been applied");
}

[Fact]
Expand Down
45 changes: 14 additions & 31 deletions AgileMapper/Api/Configuration/MapperConfigurationSpecifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,7 @@ public MapperConfigurationSpecifier From(IEnumerable<Assembly> assemblies, Func<

ThrowIfInvalidAssembliesSupplied(matchingAssemblies.Any(), nullSupplied: false);

ApplyConfigurationsIn(matchingAssemblies.SelectMany(QueryConfigurationTypesIn));
return this;
return ApplyConfigurationsIn(matchingAssemblies.SelectMany(QueryConfigurationTypesIn));
}

/// <summary>
Expand All @@ -101,12 +100,10 @@ public MapperConfigurationSpecifier From<TConfiguration>()
where TConfiguration : MapperConfiguration, new()
{
ThrowIfConfigurationAlreadyApplied(typeof(TConfiguration));
ThrowIfDependedOnConfigurationNotApplied(typeof(TConfiguration));

var configuration = new TConfiguration();
var configurationTypeChain = GetAllConfigurationTypesFor(typeof(TConfiguration));

Apply(configuration);
return this;
return ApplyConfigurationsIn(configurationTypeChain);
}

private void ThrowIfConfigurationAlreadyApplied(Type configurationType)
Expand All @@ -118,29 +115,17 @@ private void ThrowIfConfigurationAlreadyApplied(Type configurationType)
}
}

private void ThrowIfDependedOnConfigurationNotApplied(Type configurationType)
private static IEnumerable<Type> GetAllConfigurationTypesFor(Type configurationType)
{
var dependedOnTypes = GetDependedOnConfigurationTypesFor(configurationType);

if (dependedOnTypes.None())
{
return;
}

var missingDependencies = dependedOnTypes
.Filter(t => !ConfigurationApplied(t))
.ToArray();

if (missingDependencies.None())
foreach (var dependedOnType in GetDependedOnConfigurationTypesFor(configurationType))
{
return;
foreach (var nestedDependedOnType in GetAllConfigurationTypesFor(dependedOnType))
{
yield return nestedDependedOnType;
}
}

var configurationTypeName = configurationType.GetFriendlyName();
var dependencyNames = missingDependencies.Project(d => d.GetFriendlyName()).Join(", ");

throw new MappingConfigurationException(
$"Configuration {configurationTypeName} must be registered after depended-on configuration(s) {dependencyNames}");
yield return configurationType;
}

private bool ConfigurationApplied(Type configurationType)
Expand All @@ -158,12 +143,9 @@ private bool ConfigurationApplied(Type configurationType)
/// to be registered.
/// </returns>
public MapperConfigurationSpecifier FromAssemblyOf<T>()
{
ApplyConfigurationsIn(QueryConfigurationTypesIn(typeof(T).GetAssembly()));
return this;
}
=> ApplyConfigurationsIn(QueryConfigurationTypesIn(typeof(T).GetAssembly()));

private void ApplyConfigurationsIn(IEnumerable<Type> configurationTypes)
private MapperConfigurationSpecifier ApplyConfigurationsIn(IEnumerable<Type> configurationTypes)
{
var configurationData = configurationTypes
.Select(t => new ConfigurationData(t))
Expand All @@ -172,7 +154,7 @@ private void ApplyConfigurationsIn(IEnumerable<Type> configurationTypes)
if (configurationData.None(d => d.DependedOnConfigurationTypes.Any()))
{
Apply(configurationData.Project(d => d.Configuration));
return;
return this;
}

var configurationCount = configurationData.Count;
Expand Down Expand Up @@ -213,6 +195,7 @@ private void ApplyConfigurationsIn(IEnumerable<Type> configurationTypes)
.Project(kvp => configurationDataByType[kvp.Key].Configuration);

Apply(orderedConfigurations);
return this;
}

private static void InsertWithOrder(
Expand Down