Skip to content

Commit 99e1c05

Browse files
committed
Ignoring copy constructors when figuring out how to create objects, re: issue #9
1 parent 7cfe8ec commit 99e1c05

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

AgileMapper.UnitTests/WhenMappingToConstructors.cs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,22 @@ public void ShouldIgnoreConstructorsWithNoUseableDataSource()
8383
result.Value2.ShouldBeDefault();
8484
}
8585

86+
// See https://github.com/agileobjects/AgileMapper/issues/9
87+
[Fact]
88+
public void ShouldIgnoreACopyConstructor()
89+
{
90+
var source = new CopyConstructor { StringValue = "Copy!" };
91+
var result = Mapper.Map(source).ToANew<CopyConstructor>();
92+
93+
result.StringValue.ShouldBe("Copy!");
94+
}
95+
8696
#region Helper Classes
8797

88-
// ReSharper disable once ClassNeverInstantiated.Local
98+
// ReSharper disable ClassNeverInstantiated.Local
99+
// ReSharper disable UnusedMember.Local
89100
private class MultipleConstructors<T1, T2>
90101
{
91-
// ReSharper disable UnusedMember.Local
92102
public MultipleConstructors()
93103
{
94104
}
@@ -103,13 +113,29 @@ public MultipleConstructors(T1 value1, T2 value2)
103113
Value1 = value1;
104114
Value2 = value2;
105115
}
106-
// ReSharper restore UnusedMember.Local
107116

108117
public T1 Value1 { get; }
109118

110119
public T2 Value2 { get; }
111120
}
112121

122+
private class CopyConstructor
123+
{
124+
public CopyConstructor()
125+
{
126+
}
127+
128+
public CopyConstructor(CopyConstructor otherInstance)
129+
{
130+
StringValue = otherInstance.StringValue;
131+
}
132+
133+
// ReSharper disable once MemberCanBePrivate.Local
134+
public string StringValue { get; set; }
135+
}
136+
// ReSharper restore UnusedMember.Local
137+
// ReSharper restore ClassNeverInstantiated.Local
138+
113139
#endregion
114140
}
115141
}

AgileMapper/ObjectPopulation/ComplexTypes/ComplexTypeConstructionFactory.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ private static void AddNewingConstruction(ICollection<Construction> construction
9797

9898
var greediestAvailableConstructor = mapperData.InstanceVariable.Type
9999
.GetPublicInstanceConstructors()
100+
.Where(IsNotCopyConstructor)
100101
.Select(ctor => CreateConstructorData(ctor, key))
101102
.Where(ctor => ctor.CanBeConstructed)
102103
.OrderByDescending(ctor => ctor.NumberOfParameters)
@@ -117,6 +118,13 @@ private static void AddNewingConstruction(ICollection<Construction> construction
117118
constructions.Add(greediestAvailableConstructor.Construction);
118119
}
119120

121+
private static bool IsNotCopyConstructor(ConstructorInfo ctor)
122+
{
123+
// If the constructor takes an instance of itself, we'll potentially end
124+
// up in an infinite loop figuring out how to create instances for it:
125+
return ctor.GetParameters().None(p => p.ParameterType == ctor.DeclaringType);
126+
}
127+
120128
private static ConstructorData CreateConstructorData(ConstructorInfo ctor, ConstructionKey key)
121129
{
122130
var mapperData = key.MappingData.MapperData;

0 commit comments

Comments
 (0)