Skip to content

Commit 80e5019

Browse files
committed
Support for mapping through circular references via link objects / Removing unused usings
1 parent 82a16f4 commit 80e5019

File tree

9 files changed

+70
-12
lines changed

9 files changed

+70
-12
lines changed

AgileMapper.PerformanceTester/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// AgileMapper and AutoMapper perform better with this attribute applied,
66
// but ExpressMapper and Mapster throw exceptions - uncomment to test the
77
// Agile and Auto at their fastest:
8-
//[assembly: System.Security.AllowPartiallyTrustedCallers]
8+
[assembly: System.Security.AllowPartiallyTrustedCallers]
99

1010
namespace AgileObjects.AgileMapper.PerformanceTester
1111
{

AgileMapper.UnitTests/WhenMappingCircularReferences.cs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
{
33
using System;
44
using System.Collections.Generic;
5-
using System.Linq;
65
using AgileMapper.Extensions;
76
using Shouldly;
87
using TestClasses;
@@ -261,6 +260,16 @@ public void ShouldMapMultiplyRecursiveRelationships()
261260
}
262261
}
263262

263+
[Fact]
264+
public void ShouldGenerateAMappingPlanForLinkRelationships()
265+
{
266+
var plan = Mapper.GetPlanFor<Video>().Over<Video>();
267+
268+
plan.ShouldNotBeNull();
269+
plan.ShouldContain("WhenMappingCircularReferences.Video -> WhenMappingCircularReferences.Video");
270+
plan.ShouldContain(".MapRecursion(");
271+
}
272+
264273
[Fact]
265274
public void ShouldGenerateAMappingPlanForAOneToOneRelationship()
266275
{
@@ -304,6 +313,47 @@ internal class MultipleRecursor
304313
public List<MultipleRecursor> ChildRecursors { get; set; }
305314
}
306315

316+
internal class Video
317+
{
318+
public IEnumerable<VideoPresenter> Presenters { get; set; }
319+
}
320+
321+
internal class VideoPresenter
322+
{
323+
public Video Video { get; set; }
324+
325+
public Presenter Presenter { get; set; }
326+
}
327+
328+
internal class Presenter
329+
{
330+
public IEnumerable<PresenterExpertise> Expertises { get; set; }
331+
}
332+
333+
internal class PresenterExpertise
334+
{
335+
public Presenter Presenter { get; set; }
336+
337+
public Expertise Expertise { get; set; }
338+
}
339+
340+
internal class Expertise
341+
{
342+
public Subject Subject { get; set; }
343+
}
344+
345+
internal class Subject
346+
{
347+
public IEnumerable<SubjectPresenter> Presenters { get; set; }
348+
}
349+
350+
internal class SubjectPresenter
351+
{
352+
public Subject Subject { get; set; }
353+
354+
public Presenter Presenter { get; set; }
355+
}
356+
307357
#endregion
308358
}
309359
}

AgileMapper/DataSources/DataSourceSet.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ namespace AgileObjects.AgileMapper.DataSources
22
{
33
using System.Collections;
44
using System.Collections.Generic;
5-
#if !NET_STANDARD
6-
using System.Diagnostics.CodeAnalysis;
5+
#if !NET_STANDARD
6+
using System.Diagnostics.CodeAnalysis;
77
#endif
8-
using System.Linq;
98
using System.Linq.Expressions;
109
using Extensions;
1110
using Members;

AgileMapper/Members/DictionaryEntrySourceMember.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ namespace AgileObjects.AgileMapper.Members
44
#if !NET_STANDARD
55
using System.Diagnostics.CodeAnalysis;
66
#endif
7-
using System.Linq;
87
using System.Linq.Expressions;
98
using Extensions;
109
using ReadableExpressions.Extensions;

AgileMapper/Members/MemberMapperDataExtensions.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ public static bool TargetMemberEverRecurses(this IMemberMapperData mapperData)
126126
// the RecursionMapperFunc which performs the recursive mapping:
127127
return TargetMemberIsRecursionWithin(
128128
parentMapperData.TargetMember,
129-
mapperData.TargetMember.LeafMember);
129+
mapperData.TargetMember.LeafMember,
130+
new List<Type>());
130131
}
131132

132133
parentMapperData = parentMapperData.Parent;
@@ -135,7 +136,10 @@ public static bool TargetMemberEverRecurses(this IMemberMapperData mapperData)
135136
return false;
136137
}
137138

138-
private static bool TargetMemberIsRecursionWithin(QualifiedMember parentMember, Member member)
139+
private static bool TargetMemberIsRecursionWithin(
140+
QualifiedMember parentMember,
141+
Member member,
142+
ICollection<Type> checkedTypes)
139143
{
140144
while (true)
141145
{
@@ -148,7 +152,7 @@ private static bool TargetMemberIsRecursionWithin(QualifiedMember parentMember,
148152
var nonSimpleChildMembers = GlobalContext.Instance
149153
.MemberFinder
150154
.GetTargetMembers(parentMember.Type)
151-
.Where(m => !m.IsSimple)
155+
.Where(m => !m.IsSimple && !checkedTypes.Contains(m.IsEnumerable ? m.ElementType : m.Type))
152156
.ToArray();
153157

154158
if (nonSimpleChildMembers.None())
@@ -165,7 +169,10 @@ private static bool TargetMemberIsRecursionWithin(QualifiedMember parentMember,
165169
return childMember.IsRecursion;
166170
}
167171

168-
return nonSimpleChildMembers.Any(m => TargetMemberIsRecursionWithin(parentMember.Append(m), member));
172+
checkedTypes.Add(parentMember.Type);
173+
174+
return nonSimpleChildMembers.Any(m =>
175+
TargetMemberIsRecursionWithin(parentMember.Append(m), member, checkedTypes));
169176
}
170177
}
171178

@@ -375,6 +382,7 @@ private static Expression GetAccess(
375382
.MakeGenericType(contextTypes[0], contextTypes[1])
376383
.GetProperty(propertyName);
377384

385+
// ReSharper disable once AssignNullToNotNullAttribute
378386
return Expression.Property(contextAccess, property);
379387
}
380388

AgileMapper/Members/QualifiedMember.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ namespace AgileObjects.AgileMapper.Members
22
{
33
using System;
44
using System.Collections.Generic;
5+
using System.Diagnostics;
56
#if !NET_STANDARD
67
using System.Diagnostics.CodeAnalysis;
78
#endif
@@ -210,6 +211,7 @@ public bool IsRecursionRoot()
210211

211212
IQualifiedMember IQualifiedMember.Append(Member childMember) => Append(childMember);
212213

214+
[DebuggerStepThrough]
213215
public QualifiedMember Append(Member childMember)
214216
=> _childMemberCache.GetOrAdd(childMember, CreateChildMember);
215217

AgileMapper/ObjectPopulation/ComplexTypes/SourceDictionaryShortCircuitFactory.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ namespace AgileObjects.AgileMapper.ObjectPopulation.ComplexTypes
22
{
33
using System.Collections.Generic;
44
using System.Linq.Expressions;
5+
#if NET_STANDARD
56
using System.Reflection;
7+
#endif
68
using DataSources;
79
using Extensions;
810
using Members;

AgileMapper/ObjectPopulation/DerivedMappingFactory.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
{
33
using System;
44
using System.Linq.Expressions;
5-
using System.Reflection;
65
using Extensions;
76
using Members;
87

AgileMapper/ObjectPopulation/MappingDataFactory.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
namespace AgileObjects.AgileMapper.ObjectPopulation
22
{
3-
using System.Linq;
43
using System.Reflection;
54
using Enumerables;
65
using Extensions;

0 commit comments

Comments
 (0)