Skip to content

Commit 609baa6

Browse files
committed
Erroring if map-to-null conditions are configured for the same type
1 parent cb28269 commit 609baa6

File tree

5 files changed

+51
-11
lines changed

5 files changed

+51
-11
lines changed

AgileMapper.UnitTests/Configuration/WhenMappingToNull.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
namespace AgileObjects.AgileMapper.UnitTests.Configuration
22
{
33
using System;
4+
using AgileMapper.Configuration;
45
using Shouldly;
56
using TestClasses;
67
using Xunit;
@@ -91,5 +92,27 @@ public void ShouldOverwriteAPropertyToNull()
9192
target.Address.ShouldBeNull();
9293
}
9394
}
95+
96+
[Fact]
97+
public void ShouldErrorIfConditionsAreConfiguredForTheSameType()
98+
{
99+
var configEx = Should.Throw<MappingConfigurationException>(() =>
100+
{
101+
using (var mapper = Mapper.CreateNew())
102+
{
103+
mapper.WhenMapping
104+
.To<Address>()
105+
.If((o, a) => a.Line1 == null)
106+
.MapToNull();
107+
108+
mapper.WhenMapping
109+
.To<Address>()
110+
.If((o, a) => a.Line1 == string.Empty)
111+
.MapToNull();
112+
}
113+
});
114+
115+
configEx.Message.ShouldContain("already has");
116+
}
94117
}
95118
}

AgileMapper/Configuration/DerivedTypePair.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public override bool AppliesTo(IBasicMapperData mapperData)
9898
public override string ToString()
9999
{
100100
var rootSourceType = ConfigInfo.SourceType.GetFriendlyName();
101-
var rootTargetType = ConfigInfo.TargetType.GetFriendlyName();
101+
var rootTargetType = TargetTypeName;
102102
var derivedSourceType = DerivedSourceType.GetFriendlyName();
103103
var derivedTargetType = DerivedTargetType.GetFriendlyName();
104104

AgileMapper/Configuration/MapToNullCondition.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ public MapToNullCondition(MappingConfigInfo configInfo)
1111
{
1212
}
1313

14+
protected override bool ConditionsAvoidConflict(UserConfiguredItemBase otherConfiguredItem) => false;
15+
1416
protected override Expression GetConditionOrNull(IMemberMapperData mapperData, CallbackPosition position)
1517
{
1618
mapperData.Context.UsesMappingDataObjectAsParameter =

AgileMapper/Configuration/UserConfigurationSet.cs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ public bool DisableObjectTracking(IBasicMapperData basicData)
6060

6161
public void Add(MapToNullCondition condition)
6262
{
63+
ThrowIfConflictingItemExists(
64+
condition,
65+
_mapToNullConditions,
66+
c => "Type " + c.TargetTypeName + " already has a configured map-to-null condition");
67+
6368
_mapToNullConditions.Add(condition);
6469
}
6570

@@ -204,24 +209,28 @@ private void ThrowIfConflictingIgnoredMemberExists<TConfiguredItem>(
204209
Func<TConfiguredItem, string> messageFactory)
205210
where TConfiguredItem : UserConfiguredItemBase
206211
{
207-
var conflictingIgnoredMember = _ignoredMembers
208-
.FirstOrDefault(im => im.ConflictsWith(configuredItem));
209-
210-
if (conflictingIgnoredMember != null)
211-
{
212-
throw new MappingConfigurationException(messageFactory.Invoke(configuredItem));
213-
}
212+
ThrowIfConflictingItemExists(configuredItem, _ignoredMembers, messageFactory);
214213
}
215214

216215
internal void ThrowIfConflictingDataSourceExists<TConfiguredItem>(
217216
TConfiguredItem configuredItem,
218217
Func<TConfiguredItem, string> messageFactory)
219218
where TConfiguredItem : UserConfiguredItemBase
220219
{
221-
var conflictingDataSource = _dataSourceFactories
220+
ThrowIfConflictingItemExists(configuredItem, _dataSourceFactories, messageFactory);
221+
}
222+
223+
private static void ThrowIfConflictingItemExists<TConfiguredItem, TExistingItem>(
224+
TConfiguredItem configuredItem,
225+
IEnumerable<TExistingItem> existingItems,
226+
Func<TConfiguredItem, string> messageFactory)
227+
where TConfiguredItem : UserConfiguredItemBase
228+
where TExistingItem : UserConfiguredItemBase
229+
{
230+
var conflictingItem = existingItems
222231
.FirstOrDefault(dsf => dsf.ConflictsWith(configuredItem));
223232

224-
if (conflictingDataSource != null)
233+
if (conflictingItem != null)
225234
{
226235
throw new MappingConfigurationException(messageFactory.Invoke(configuredItem));
227236
}

AgileMapper/Configuration/UserConfiguredItemBase.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Members;
99
using ObjectPopulation;
1010
using ReadableExpressions;
11+
using ReadableExpressions.Extensions;
1112

1213
internal abstract class UserConfiguredItemBase : IComparable<UserConfiguredItemBase>
1314
{
@@ -42,13 +43,15 @@ protected UserConfiguredItemBase(MappingConfigInfo configInfo, QualifiedMember t
4243

4344
protected MappingConfigInfo ConfigInfo { get; }
4445

46+
public string TargetTypeName => ConfigInfo.TargetType.GetFriendlyName();
47+
4548
public QualifiedMember TargetMember { get; }
4649

4750
public bool HasConfiguredCondition => ConfigInfo.HasCondition;
4851

4952
public virtual bool ConflictsWith(UserConfiguredItemBase otherConfiguredItem)
5053
{
51-
if (HasConfiguredCondition || otherConfiguredItem.HasConfiguredCondition)
54+
if (ConditionsAvoidConflict(otherConfiguredItem))
5255
{
5356
return false;
5457
}
@@ -61,6 +64,9 @@ public virtual bool ConflictsWith(UserConfiguredItemBase otherConfiguredItem)
6164
return false;
6265
}
6366

67+
protected virtual bool ConditionsAvoidConflict(UserConfiguredItemBase otherConfiguredItem)
68+
=> HasConfiguredCondition || otherConfiguredItem.HasConfiguredCondition;
69+
6470
protected virtual bool MembersConflict(QualifiedMember otherMember)
6571
=> TargetMember.Matches(otherMember);
6672

0 commit comments

Comments
 (0)