Skip to content

Commit 7491b28

Browse files
authored
Configuration classes (#67)
* Start of support for specifying mapper configurations in dedicated classes * Surfacing all mapper configuration options to a MapperConfiguration * Support for scanning MapperConfigurations in an assembly of a given type * Support for passing services through the MapperConfigurations * Test coverage for MappingConfiguration registration via the static API * Support for loading MapperConfigurations from a collection of given assemblies * Fixing query projection * Guarding against incorrect MapperConfiguration use
1 parent ddfd24d commit 7491b28

18 files changed

+765
-29
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
namespace AgileObjects.AgileMapper.UnitTests.MoreTestClasses
2+
{
3+
using System.Collections.Generic;
4+
using Configuration;
5+
6+
public class ServiceDictionaryMapperConfiguration : MapperConfiguration
7+
{
8+
protected override void Configure()
9+
{
10+
var mappersByName = GetServiceOrNull<Dictionary<string, IMapper>>();
11+
12+
var mapper1 = CreateNewMapper();
13+
14+
mapper1.WhenMapping
15+
.From<Dog>()
16+
.To<Dog>()
17+
.Map((s, t) => "BARK 1!")
18+
.To(t => t.WoofSound);
19+
20+
mappersByName.Add("DogMapper1", mapper1);
21+
22+
var mapper2 = CreateNewMapper();
23+
24+
mapper2.WhenMapping
25+
.From<Dog>()
26+
.To<Dog>()
27+
.Map((s, t) => "BARK 2!")
28+
.To(t => t.WoofSound);
29+
30+
mappersByName.Add("DogMapper2", mapper2);
31+
}
32+
33+
public static bool VerifyConfigured(Dictionary<string, IMapper> mappersByName)
34+
{
35+
if (!mappersByName.ContainsKey("DogMapper1") || !mappersByName.ContainsKey("DogMapper2"))
36+
{
37+
return false;
38+
}
39+
40+
var result1 = mappersByName["DogMapper1"].DeepClone(new Dog());
41+
42+
if (result1.WoofSound != "BARK 1!")
43+
{
44+
return false;
45+
}
46+
47+
var result2 = mappersByName["DogMapper2"].DeepClone(new Dog());
48+
49+
if (result2.WoofSound != "BARK 2!")
50+
{
51+
return false;
52+
}
53+
54+
return true;
55+
}
56+
}
57+
}

AgileMapper.UnitTests.NonParallel/AgileMapper.UnitTests.NonParallel.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
<Link>VersionInfo.cs</Link>
6969
</Compile>
7070
<Compile Include="Configuration\Inline\WhenConfiguringDataSourcesInline.cs" />
71+
<Compile Include="Configuration\WhenApplyingMapperConfigurations.cs" />
7172
<Compile Include="Configuration\WhenConfiguringDataSources.cs" />
7273
<Compile Include="Configuration\WhenConfiguringDerivedTypes.cs" />
7374
<Compile Include="Configuration\WhenConfiguringMappingCallbacks.cs" />
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
namespace AgileObjects.AgileMapper.UnitTests.NonParallel.Configuration
2+
{
3+
using System.Collections.Generic;
4+
using MoreTestClasses;
5+
using Xunit;
6+
using UnitTestsMapperConfigurations = UnitTests.Configuration.WhenApplyingMapperConfigurations;
7+
8+
public class WhenApplyingMapperConfigurations : NonParallelTestsBase
9+
{
10+
[Fact]
11+
public void ShouldApplyMapperConfigurationsInGivenAssembliesViaTheStaticApi()
12+
{
13+
TestThenReset(() =>
14+
{
15+
var mappersByName = new Dictionary<string, IMapper>();
16+
17+
Mapper.WhenMapping
18+
.UseConfigurations
19+
.FromAssemblyOf<UnitTestsMapperConfigurations>()
20+
.FromAssemblyOf<AnimalBase>(mappersByName);
21+
22+
UnitTestsMapperConfigurations.PfiToPfsMapperConfiguration.VerifyConfigured(Mapper.Default);
23+
UnitTestsMapperConfigurations.PfsToPfiMapperConfiguration.VerifyConfigured(Mapper.Default);
24+
25+
ServiceDictionaryMapperConfiguration
26+
.VerifyConfigured(mappersByName)
27+
.ShouldBeTrue();
28+
});
29+
}
30+
31+
[Fact]
32+
public void ShouldProvideRegisteredServicesToMapperConfigurationsViaTheStaticApi()
33+
{
34+
var mappersByName = new Dictionary<string, IMapper>();
35+
36+
TestThenReset(() =>
37+
{
38+
Mapper.WhenMapping
39+
.UseConfigurations.From<ServiceDictionaryMapperConfiguration>(mappersByName);
40+
41+
ServiceDictionaryMapperConfiguration
42+
.VerifyConfigured(mappersByName)
43+
.ShouldBeTrue();
44+
});
45+
}
46+
}
47+
}

AgileMapper.UnitTests.NonParallel/NonParallelTestsBase.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ protected void TestThenReset(Action testAction)
1313
finally
1414
{
1515
Mapper.ResetDefaultInstance();
16+
GlobalContext.Instance.DerivedTypes.Reset();
1617
}
1718
}
1819
}

AgileMapper.UnitTests/AgileMapper.UnitTests.csproj

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<DebugType>full</DebugType>
2727
<Optimize>false</Optimize>
2828
<OutputPath>bin\Debug\</OutputPath>
29-
<DefineConstants>DEBUG;TRACE</DefineConstants>
29+
<DefineConstants>DEBUG;TRACE;NET40</DefineConstants>
3030
<ErrorReport>prompt</ErrorReport>
3131
<WarningLevel>4</WarningLevel>
3232
<Prefer32Bit>false</Prefer32Bit>
@@ -35,7 +35,7 @@
3535
<DebugType>pdbonly</DebugType>
3636
<Optimize>true</Optimize>
3737
<OutputPath>bin\Release\</OutputPath>
38-
<DefineConstants>TRACE</DefineConstants>
38+
<DefineConstants>TRACE;NET40</DefineConstants>
3939
<ErrorReport>prompt</ErrorReport>
4040
<WarningLevel>4</WarningLevel>
4141
<Prefer32Bit>false</Prefer32Bit>
@@ -85,6 +85,7 @@
8585
<Compile Include="..\VersionInfo.cs">
8686
<Link>VersionInfo.cs</Link>
8787
</Compile>
88+
<Compile Include="Configuration\AssemblyScanningTestClassBase.cs" />
8889
<Compile Include="Configuration\Inline\InlineMappingExtensions.cs" />
8990
<Compile Include="Configuration\Inline\WhenConfiguringCallbacksInline.cs" />
9091
<Compile Include="Configuration\Inline\WhenConfiguringConstructorDataSourcesInline.cs" />
@@ -102,6 +103,8 @@
102103
<Compile Include="Configuration\Inline\WhenMappingToNullInline.cs" />
103104
<Compile Include="Configuration\Inline\WhenValidatingMappingsInline.cs" />
104105
<Compile Include="Configuration\Inline\WhenViewingMappingPlans.cs" />
106+
<Compile Include="Configuration\WhenApplyingMapperConfigurations.cs" />
107+
<Compile Include="Configuration\WhenApplyingMapperConfigurationsIncorrectly.cs" />
105108
<Compile Include="Configuration\WhenViewingMappingPlans.cs" />
106109
<Compile Include="Dictionaries\WhenMappingFromDictionariesOnToComplexTypes.cs" />
107110
<Compile Include="Dictionaries\WhenMappingFromDictionariesOnToEnumerableMembers.cs" />
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace AgileObjects.AgileMapper.UnitTests.Configuration
2+
{
3+
using System;
4+
5+
public abstract class AssemblyScanningTestClassBase
6+
{
7+
protected void TestThenReset(Action testAction)
8+
{
9+
try
10+
{
11+
testAction.Invoke();
12+
}
13+
finally
14+
{
15+
GlobalContext.Instance.DerivedTypes.Reset();
16+
}
17+
}
18+
}
19+
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
namespace AgileObjects.AgileMapper.UnitTests.Configuration
2+
{
3+
#if NET40
4+
using System;
5+
#endif
6+
using System.Collections.Generic;
7+
using AgileMapper.Configuration;
8+
using MoreTestClasses;
9+
using NetStandardPolyfills;
10+
using TestClasses;
11+
using Xunit;
12+
13+
public class WhenApplyingMapperConfigurations : AssemblyScanningTestClassBase
14+
{
15+
[Fact]
16+
public void ShouldApplyAGivenMapperConfiguration()
17+
{
18+
TestThenReset(() =>
19+
{
20+
using (var mapper = Mapper.CreateNew())
21+
{
22+
mapper.WhenMapping
23+
.UseConfigurations.From<PfiToPfsMapperConfiguration>();
24+
25+
PfiToPfsMapperConfiguration.VerifyConfigured(mapper);
26+
}
27+
});
28+
}
29+
30+
[Fact]
31+
public void ShouldApplyMapperConfigurationsInAGivenTypeAssembly()
32+
{
33+
TestThenReset(() =>
34+
{
35+
using (var mapper = Mapper.CreateNew())
36+
{
37+
mapper.WhenMapping
38+
.UseConfigurations.FromAssemblyOf<WhenApplyingMapperConfigurations>();
39+
40+
PfiToPfsMapperConfiguration.VerifyConfigured(mapper);
41+
PfsToPfiMapperConfiguration.VerifyConfigured(mapper);
42+
}
43+
});
44+
}
45+
46+
[Fact]
47+
public void ShouldProvideRegisteredServicesToMapperConfigurations()
48+
{
49+
TestThenReset(() =>
50+
{
51+
using (var mapper = Mapper.CreateNew())
52+
{
53+
var mappersByName = new Dictionary<string, IMapper>();
54+
55+
mapper.WhenMapping
56+
.UseConfigurations.FromAssemblyOf<AnimalBase>(mappersByName);
57+
58+
ServiceDictionaryMapperConfiguration
59+
.VerifyConfigured(mappersByName)
60+
.ShouldBeTrue();
61+
}
62+
});
63+
}
64+
65+
#if NET40
66+
[Fact]
67+
public void ShouldApplyMapperConfigurationsFromGivenAssemblies()
68+
{
69+
TestThenReset(() =>
70+
{
71+
using (var mapper = Mapper.CreateNew())
72+
{
73+
var mappersByName = new Dictionary<string, IMapper>();
74+
75+
mapper.WhenMapping
76+
.UseConfigurations.From(AppDomain.CurrentDomain.GetAssemblies(), mappersByName);
77+
78+
PfiToPfsMapperConfiguration.VerifyConfigured(mapper);
79+
PfsToPfiMapperConfiguration.VerifyConfigured(mapper);
80+
81+
ServiceDictionaryMapperConfiguration
82+
.VerifyConfigured(mappersByName)
83+
.ShouldBeTrue();
84+
}
85+
});
86+
}
87+
#endif
88+
89+
[Fact]
90+
public void ShouldFilterMapperConfigurationsFromGivenAssemblies()
91+
{
92+
TestThenReset(() =>
93+
{
94+
using (var mapper = Mapper.CreateNew())
95+
{
96+
mapper.WhenMapping.UseConfigurations.From(
97+
new[]
98+
{
99+
typeof(PfiToPfsMapperConfiguration).GetAssembly(),
100+
typeof(ServiceDictionaryMapperConfiguration).GetAssembly()
101+
},
102+
assembly => !assembly.FullName.Contains(nameof(MoreTestClasses)));
103+
104+
PfiToPfsMapperConfiguration.VerifyConfigured(mapper);
105+
PfsToPfiMapperConfiguration.VerifyConfigured(mapper);
106+
}
107+
});
108+
}
109+
110+
#region Helper Classes
111+
112+
public class PfiToPfsMapperConfiguration : MapperConfiguration
113+
{
114+
protected override void Configure()
115+
{
116+
WhenMapping
117+
.From<PublicField<int>>()
118+
.ToANew<PublicField<string>>()
119+
.Map(ctx => ctx.Source.Value * 2)
120+
.To(t => t.Value);
121+
122+
GetPlanFor<PublicField<int>>().ToANew<PublicField<string>>();
123+
}
124+
125+
public static void VerifyConfigured(IMapper mapper)
126+
{
127+
var source = new PublicField<int> { Value = 123 };
128+
var result = mapper.Map(source).ToANew<PublicField<string>>();
129+
130+
result.Value.ShouldBe(246);
131+
}
132+
}
133+
134+
// ReSharper disable once ClassNeverInstantiated.Local
135+
public class PfsToPfiMapperConfiguration : MapperConfiguration
136+
{
137+
protected override void Configure()
138+
{
139+
WhenMapping
140+
.From<PublicField<string>>()
141+
.ToANew<PublicField<int>>()
142+
.Map(ctx => ctx.Source.Value + "10")
143+
.To(t => t.Value);
144+
145+
GetPlansFor<PublicField<string>>().To<PublicField<int>>();
146+
}
147+
148+
public static void VerifyConfigured(IMapper mapper)
149+
{
150+
var source = new PublicField<string> { Value = "10" };
151+
var result = mapper.Map(source).ToANew<PublicField<int>>();
152+
153+
result.Value.ShouldBe(1010);
154+
}
155+
}
156+
157+
#endregion
158+
}
159+
}

0 commit comments

Comments
 (0)