Skip to content

Commit 36fc7c0

Browse files
authored
To root target update (#70)
* - Erroring if simple data sources are configured for non-simple targets - Renaming ToRootTarget -> ToTarget - Improving invalid data source configuration error messages * Processing source member runtime type access expressions using member expression equivalence, fixes issue #68 * Support for applying configured root sources to nested complex type members, re: issue #69 * Applying configured root sources at any mapping level in target Dictionary and ExpandoObject mapping
1 parent d39670d commit 36fc7c0

15 files changed

+335
-92
lines changed

AgileMapper.UnitTests/Configuration/Inline/WhenConfiguringDataSourcesInline.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ public void ShouldApplyAConfiguredRootSourceMember()
340340
.MapUsing(mapper)
341341
.ToANew<PublicTwoFields<int, int>>(cfg => cfg
342342
.Map((s, ptf) => s.Value)
343-
.ToRootTarget());
343+
.ToTarget());
344344

345345
result.Value1.ShouldBe(8392);
346346
result.Value2.ShouldBe(5482);
@@ -361,7 +361,7 @@ public void ShouldApplyAConfiguredRootSourceObjectMember()
361361
.Map(source1)
362362
.ToANew<PublicProperty<string>>(cfg => cfg
363363
.Map((s, t) => s.Value)
364-
.ToRootTarget());
364+
.ToTarget());
365365

366366
result1.Value.ShouldBe("Hello!");
367367

@@ -374,7 +374,7 @@ public void ShouldApplyAConfiguredRootSourceObjectMember()
374374
.Map(source2)
375375
.ToANew<PublicProperty<string>>(cfg => cfg
376376
.Map((s, t) => s.Value)
377-
.ToRootTarget());
377+
.ToTarget());
378378

379379
result2.Value.ShouldBe("Goodbye!");
380380

AgileMapper.UnitTests/Configuration/WhenConfiguringDataSources.cs

Lines changed: 128 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,7 @@ public void ShouldAllowIdAndIdentifierConfiguration()
996996

997997
// See https://github.com/agileobjects/AgileMapper/issues/64
998998
[Fact]
999-
public void ShouldApplyAConfiguredRootSourceMember()
999+
public void ShouldApplyAConfiguredRootSource()
10001000
{
10011001
using (var mapper = Mapper.CreateNew())
10021002
{
@@ -1005,8 +1005,8 @@ public void ShouldApplyAConfiguredRootSourceMember()
10051005
mapper.WhenMapping
10061006
.From(source)
10071007
.To<PublicTwoFields<int, int>>()
1008-
.Map((s, ptf) => s.Value)
1009-
.ToRootTarget();
1008+
.Map(ctx => ctx.Source.Value)
1009+
.ToTarget();
10101010

10111011
var result = source
10121012
.MapUsing(mapper)
@@ -1018,15 +1018,15 @@ public void ShouldApplyAConfiguredRootSourceMember()
10181018
}
10191019

10201020
[Fact]
1021-
public void ShouldApplyANestedOverwriteConfiguredRootSourceMember()
1021+
public void ShouldApplyANestedOverwriteConfiguredRootSource()
10221022
{
10231023
using (var mapper = Mapper.CreateNew())
10241024
{
10251025
mapper.WhenMapping
10261026
.From<PublicTwoFields<int, PublicField<PublicTwoFields<int, int>>>>()
10271027
.Over<PublicTwoFields<int, int>>()
10281028
.Map((s, t) => s.Value2.Value)
1029-
.ToRootTarget();
1029+
.ToTarget();
10301030

10311031
var source = new PublicTwoFields<int, PublicField<PublicTwoFields<int, int>>>
10321032
{
@@ -1054,7 +1054,7 @@ public void ShouldApplyANestedOverwriteConfiguredRootSourceMember()
10541054
}
10551055

10561056
[Fact]
1057-
public void ShouldHandleAConfiguredRootSourceMemberNullValue()
1057+
public void ShouldHandleAConfiguredRootSourceNullValue()
10581058
{
10591059
using (var mapper = Mapper.CreateNew())
10601060
{
@@ -1065,7 +1065,7 @@ public void ShouldHandleAConfiguredRootSourceMemberNullValue()
10651065
.To(t => t.Value1)
10661066
.And
10671067
.Map((mc, t) => mc.Address)
1068-
.ToRootTarget();
1068+
.ToTarget();
10691069

10701070
var source = new MysteryCustomer { Name = "Nelly", Address = default(Address) };
10711071

@@ -1077,7 +1077,7 @@ public void ShouldHandleAConfiguredRootSourceMemberNullValue()
10771077
}
10781078

10791079
[Fact]
1080-
public void ShouldApplyAConfiguredRootSourceMemberConditionally()
1080+
public void ShouldApplyAConfiguredRootSourceConditionally()
10811081
{
10821082
using (var mapper = Mapper.CreateNew())
10831083
{
@@ -1086,7 +1086,7 @@ public void ShouldApplyAConfiguredRootSourceMemberConditionally()
10861086
.OnTo<PublicTwoFields<int, int>>()
10871087
.If((s, t) => s.Value1.Value > 5)
10881088
.Map((s, t) => s.Value1)
1089-
.ToRootTarget();
1089+
.ToTarget();
10901090

10911091
mapper.WhenMapping
10921092
.From<PublicPropertyStruct<int>>()
@@ -1122,16 +1122,102 @@ public void ShouldApplyAConfiguredRootSourceMemberConditionally()
11221122
}
11231123
}
11241124

1125+
// See https://github.com/agileobjects/AgileMapper/issues/68
11251126
[Fact]
1126-
public void ShouldApplyAConfiguredRootSourceEnumerableMember()
1127+
public void ShouldSupportConfiguringARootSourceUsingMappingContext()
1128+
{
1129+
using (var mapper = Mapper.CreateNew())
1130+
{
1131+
mapper.WhenMapping
1132+
.From<Model>()
1133+
.To<ModelDto>()
1134+
.Map(ctx => ctx.Source.Statistics)
1135+
.ToTarget();
1136+
1137+
var source = new Model
1138+
{
1139+
SomeOtherProperties = "jyutrgf",
1140+
Statistics = new Statistics
1141+
{
1142+
Ranking = 0.5f,
1143+
SomeOtherRankingStuff = "uityjtgrf"
1144+
}
1145+
};
1146+
1147+
var result = mapper.Map(source).ToANew<ModelDto>();
1148+
1149+
result.SomeOtherProperties.ShouldBe("jyutrgf");
1150+
result.Ranking.ShouldBe(0.5f);
1151+
result.SomeOtherRankingStuff.ShouldBe("uityjtgrf");
1152+
}
1153+
}
1154+
1155+
[Fact]
1156+
public void ShouldApplyAConfiguredRootSourceToANestedMember()
1157+
{
1158+
using (var mapper = Mapper.CreateNew())
1159+
{
1160+
mapper.WhenMapping
1161+
.From<PublicField<PublicField<string>>>()
1162+
.To<PublicField<int>>()
1163+
.Map(ctx => ctx.Source.Value)
1164+
.ToTarget();
1165+
1166+
var source = new PublicField<PublicField<PublicField<string>>>
1167+
{
1168+
Value = new PublicField<PublicField<string>>
1169+
{
1170+
Value = new PublicField<string> { Value = "53632" }
1171+
}
1172+
};
1173+
1174+
var result = mapper.Map(source).ToANew<PublicField<PublicField<int>>>();
1175+
1176+
result.Value.Value.ShouldBe(53632);
1177+
}
1178+
}
1179+
1180+
[Fact]
1181+
public void ShouldApplyAConfiguredRootSourceToAnEnumerableElement()
1182+
{
1183+
using (var mapper = Mapper.CreateNew())
1184+
{
1185+
mapper.WhenMapping
1186+
.From<PublicField<PublicField<string>>>()
1187+
.ToANew<PublicField<string>>()
1188+
.Map(ctx => ctx.Source.Value)
1189+
.ToTarget();
1190+
1191+
var source = new[]
1192+
{
1193+
new PublicField<PublicField<string>>
1194+
{
1195+
Value = new PublicField<string> { Value = "kjfcrkjnad" }
1196+
},
1197+
new PublicField<PublicField<string>>
1198+
{
1199+
Value = new PublicField<string> { Value = "owkjwsnbsgtf" }
1200+
}
1201+
};
1202+
1203+
var result = mapper.Map(source).ToANew<Collection<PublicField<string>>>();
1204+
1205+
result.Count.ShouldBe(2);
1206+
result.First().Value.ShouldBe("kjfcrkjnad");
1207+
result.Second().Value.ShouldBe("owkjwsnbsgtf");
1208+
}
1209+
}
1210+
1211+
[Fact]
1212+
public void ShouldApplyAConfiguredEnumerableRootSource()
11271213
{
11281214
using (var mapper = Mapper.CreateNew())
11291215
{
11301216
mapper.WhenMapping
11311217
.From<PublicTwoFields<Address, Address[]>>()
11321218
.To<List<Address>>()
11331219
.Map((s, r) => s.Value2)
1134-
.ToRootTarget();
1220+
.ToTarget();
11351221

11361222
var source = new PublicTwoFields<Address, Address[]>
11371223
{
@@ -1160,7 +1246,7 @@ public void ShouldApplyAConfiguredRootSourceEnumerableMember()
11601246
}
11611247

11621248
[Fact]
1163-
public void ShouldApplyMultipleConfiguredRootSourceComplexTypeMembers()
1249+
public void ShouldApplyMultipleConfiguredComplexTypeRootSources()
11641250
{
11651251
using (var mapper = Mapper.CreateNew())
11661252
{
@@ -1174,10 +1260,10 @@ public void ShouldApplyMultipleConfiguredRootSourceComplexTypeMembers()
11741260
.From(source)
11751261
.To<PublicTwoFields<string, string>>()
11761262
.Map((s, t) => s.PropertyOne)
1177-
.ToRootTarget()
1263+
.ToTarget()
11781264
.And
11791265
.Map((s, t) => s.PropertyTwo)
1180-
.ToRootTarget();
1266+
.ToTarget();
11811267

11821268
var result = mapper.Map(source).ToANew<PublicTwoFields<string, string>>();
11831269

@@ -1187,18 +1273,18 @@ public void ShouldApplyMultipleConfiguredRootSourceComplexTypeMembers()
11871273
}
11881274

11891275
[Fact]
1190-
public void ShouldApplyMultipleConfiguredRootSourceEnumerableMembers()
1276+
public void ShouldApplyMultipleConfiguredEnumerableRootSources()
11911277
{
11921278
using (var mapper = Mapper.CreateNew())
11931279
{
11941280
mapper.WhenMapping
11951281
.From<PublicTwoFields<int[], long[]>>()
11961282
.To<decimal[]>()
1197-
.Map((s, t) => s.Value1)
1198-
.ToRootTarget()
1283+
.Map(xtx => xtx.Source.Value1)
1284+
.ToTarget()
11991285
.And
12001286
.Map((s, t) => s.Value2)
1201-
.ToRootTarget();
1287+
.ToTarget();
12021288

12031289
var source = new PublicTwoFields<int[], long[]>
12041290
{
@@ -1212,14 +1298,34 @@ public void ShouldApplyMultipleConfiguredRootSourceEnumerableMembers()
12121298
}
12131299
}
12141300

1215-
// ReSharper disable once ClassNeverInstantiated.Local
1216-
// ReSharper disable UnusedAutoPropertyAccessor.Local
1217-
private class IdTester
1301+
internal class IdTester
12181302
{
12191303
public int ClassId { get; set; }
12201304

12211305
public int ClassIdentifier { get; set; }
12221306
}
1223-
// ReSharper restore UnusedAutoPropertyAccessor.Local
1307+
1308+
internal class Statistics
1309+
{
1310+
public float Ranking { get; set; }
1311+
1312+
public string SomeOtherRankingStuff { get; set; }
1313+
}
1314+
1315+
internal class Model
1316+
{
1317+
public string SomeOtherProperties { get; set; }
1318+
1319+
public Statistics Statistics { get; set; }
1320+
}
1321+
1322+
internal class ModelDto
1323+
{
1324+
public string SomeOtherProperties { get; set; }
1325+
1326+
public float Ranking { get; set; }
1327+
1328+
public string SomeOtherRankingStuff { get; set; }
1329+
}
12241330
}
12251331
}

AgileMapper.UnitTests/Configuration/WhenConfiguringDataSourcesIncorrectly.cs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,44 @@ public void ShouldErrorIfUnconvertibleConstructorValueConstantSpecified()
254254
configurationException.Message.ShouldContain("Unable to convert");
255255
}
256256

257+
[Fact]
258+
public void ShouldErrorIfSimpleTypeConfiguredForComplexTarget()
259+
{
260+
var configurationException = Should.Throw<MappingConfigurationException>(() =>
261+
{
262+
using (var mapper = Mapper.CreateNew())
263+
{
264+
mapper.WhenMapping
265+
.From<Person>()
266+
.To<Person>()
267+
.Map((s, t) => s.Id)
268+
.To(t => t.Address);
269+
}
270+
});
271+
272+
configurationException.Message.ShouldContain(
273+
"Person.Id of type 'Guid' cannot be mapped to target type 'Address'");
274+
}
275+
276+
[Fact]
277+
public void ShouldErrorIfSimpleTypeConfiguredForEnumerableTarget()
278+
{
279+
var configurationException = Should.Throw<MappingConfigurationException>(() =>
280+
{
281+
using (var mapper = Mapper.CreateNew())
282+
{
283+
mapper.WhenMapping
284+
.From<PublicField<int>>()
285+
.To<PublicTwoFields<int[], int>>()
286+
.Map((s, t) => s.Value)
287+
.To(t => t.Value1);
288+
}
289+
});
290+
291+
configurationException.Message.ShouldContain(
292+
"PublicField<int>.Value of type 'int' cannot be mapped to target type 'int[]'");
293+
}
294+
257295
[Fact]
258296
public void ShouldErrorIfTargetParameterConfiguredAsTarget()
259297
{
@@ -283,12 +321,12 @@ public void ShouldErrorIfRootTargetSimpleTypeConstantDataSourceConfigured()
283321
.From<PublicProperty<int>>()
284322
.To<PublicField<Guid>>()
285323
.Map("No no no no no")
286-
.ToRootTarget();
324+
.ToTarget();
287325
}
288326
});
289327

290328
configurationException.Message.ShouldContain(
291-
"'string' cannot be mapped to root target type 'PublicField<Guid>'");
329+
"'string' cannot be mapped to target type 'PublicField<Guid>'");
292330
}
293331

294332
[Fact]
@@ -302,14 +340,14 @@ public void ShouldErrorIfRootTargetSimpleTypeMemberDataSourceConfigured()
302340
.From<PublicProperty<int>>()
303341
.To<PublicField<long>>()
304342
.Map(ctx => ctx.Source.Value)
305-
.ToRootTarget();
343+
.ToTarget();
306344
}
307345
});
308346

309347
configurationException.Message.ShouldContain("PublicProperty<int>.Value");
310348

311349
configurationException.Message.ShouldContain(
312-
"'int' cannot be mapped to root target type 'PublicField<long>'");
350+
"'int' cannot be mapped to target type 'PublicField<long>'");
313351
}
314352
}
315353
}

0 commit comments

Comments
 (0)