Skip to content

Commit b4114d2

Browse files
committed
CSHARP-1856: Calling SetOrder was not working because the sorting was happening too early.
1 parent 10b3b67 commit b4114d2

File tree

3 files changed

+153
-37
lines changed

3 files changed

+153
-37
lines changed

src/MongoDB.Bson/Serialization/BsonClassMap.cs

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public class BsonClassMap
5454
private readonly bool _isAnonymous;
5555
private readonly List<BsonMemberMap> _allMemberMaps; // includes inherited member maps
5656
private readonly ReadOnlyCollection<BsonMemberMap> _allMemberMapsReadonly;
57-
private readonly List<BsonMemberMap> _declaredMemberMaps; // only the members declared in this class
57+
private List<BsonMemberMap> _declaredMemberMaps; // only the members declared in this class
5858
private readonly BsonTrie<int> _elementTrie;
5959

6060
private bool _frozen; // once a class map has been frozen no further changes are allowed
@@ -490,6 +490,7 @@ public BsonClassMap Freeze()
490490
_ignoreExtraElementsIsInherited = true;
491491
}
492492
}
493+
_declaredMemberMaps = _declaredMemberMaps.OrderBy(m => m.Order).ToList(); // we're counting on OrderBy being a stable sort
493494
_allMemberMaps.AddRange(_declaredMemberMaps);
494495

495496
if (_idMemberMap == null)
@@ -928,7 +929,7 @@ public void Reset()
928929

929930
_creatorMaps.Clear();
930931
_creator = null;
931-
_declaredMemberMaps.Clear();
932+
_declaredMemberMaps = new List<BsonMemberMap>();
932933
_discriminator = _classType.Name;
933934
_discriminatorIsRequired = false;
934935
_extraElementsMemberMap = null;
@@ -1192,47 +1193,12 @@ private void AutoMapClass()
11921193
{
11931194
new ConventionRunner(_conventionPack).Apply(this);
11941195

1195-
OrderMembers();
11961196
foreach (var memberMap in _declaredMemberMaps)
11971197
{
11981198
TryFindShouldSerializeMethod(memberMap);
11991199
}
12001200
}
12011201

1202-
private void OrderMembers()
1203-
{
1204-
// only auto map properties declared in this class (and not in base classes)
1205-
var hasOrderedElements = false;
1206-
var hasUnorderedElements = false;
1207-
foreach (var memberMap in _declaredMemberMaps)
1208-
{
1209-
if (memberMap.Order != int.MaxValue)
1210-
{
1211-
hasOrderedElements |= true;
1212-
}
1213-
else
1214-
{
1215-
hasUnorderedElements |= true;
1216-
}
1217-
}
1218-
1219-
if (hasOrderedElements)
1220-
{
1221-
if (hasUnorderedElements)
1222-
{
1223-
// split out the unordered elements and add them back at the end (because Sort is unstable, see online help)
1224-
var unorderedElements = new List<BsonMemberMap>(_declaredMemberMaps.Where(pm => pm.Order == int.MaxValue));
1225-
_declaredMemberMaps.RemoveAll(m => m.Order == int.MaxValue);
1226-
_declaredMemberMaps.Sort((x, y) => x.Order.CompareTo(y.Order));
1227-
_declaredMemberMaps.AddRange(unorderedElements);
1228-
}
1229-
else
1230-
{
1231-
_declaredMemberMaps.Sort((x, y) => x.Order.CompareTo(y.Order));
1232-
}
1233-
}
1234-
}
1235-
12361202
private void TryFindShouldSerializeMethod(BsonMemberMap memberMap)
12371203
{
12381204
// see if the class has a method called ShouldSerializeXyz where Xyz is the name of this member

tests/MongoDB.Bson.Tests/MongoDB.Bson.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@
134134
<Compile Include="Serialization\Attributes\BsonConstructorAttributeTests.cs" />
135135
<Compile Include="Serialization\Attributes\BsonRepresentationAttributeTests.cs" />
136136
<Compile Include="Serialization\BsonClassMapAutoMappingTests.cs" />
137+
<Compile Include="Serialization\BsonClassMapSetOrderTests.cs" />
137138
<Compile Include="Serialization\BsonClassMapTests.cs" />
138139
<Compile Include="Serialization\BsonMemberMapDefaultValueCreatorTests.cs" />
139140
<Compile Include="Serialization\BsonMemberMapTests.cs" />
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/* Copyright 2016 MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System.Linq;
17+
using FluentAssertions;
18+
using MongoDB.Bson.Serialization;
19+
using Xunit;
20+
21+
namespace MongoDB.Bson.Tests.Serialization
22+
{
23+
public class BsonClassMapSetOrderTests
24+
{
25+
[Fact]
26+
public void SetOrder_not_called()
27+
{
28+
var cm = new BsonClassMap<C>();
29+
cm.AutoMap();
30+
cm.Freeze();
31+
32+
cm.AllMemberMaps.Select(m => m.MemberName).Should().Equal("Id", "X", "Y");
33+
}
34+
35+
[Fact]
36+
public void SetOrder_Id_1_called()
37+
{
38+
var cm = new BsonClassMap<C>();
39+
cm.AutoMap();
40+
cm.GetMemberMap("Id").SetOrder(1);
41+
cm.Freeze();
42+
43+
cm.AllMemberMaps.Select(m => m.MemberName).Should().Equal("Id", "X", "Y");
44+
}
45+
46+
[Fact]
47+
public void SetOrder_X_1_called()
48+
{
49+
var cm = new BsonClassMap<C>();
50+
cm.AutoMap();
51+
cm.GetMemberMap("X").SetOrder(1);
52+
cm.Freeze();
53+
54+
cm.AllMemberMaps.Select(m => m.MemberName).Should().Equal("X", "Id", "Y");
55+
}
56+
57+
[Fact]
58+
public void SetOrder_Y_1_called()
59+
{
60+
var cm = new BsonClassMap<C>();
61+
cm.AutoMap();
62+
cm.GetMemberMap("Y").SetOrder(1);
63+
cm.Freeze();
64+
65+
cm.AllMemberMaps.Select(m => m.MemberName).Should().Equal("Y", "Id", "X");
66+
}
67+
68+
[Fact]
69+
public void SetOrder_Id_1_X_2_called()
70+
{
71+
var cm = new BsonClassMap<C>();
72+
cm.AutoMap();
73+
cm.GetMemberMap("Id").SetOrder(1);
74+
cm.GetMemberMap("X").SetOrder(2);
75+
cm.Freeze();
76+
77+
cm.AllMemberMaps.Select(m => m.MemberName).Should().Equal("Id", "X", "Y");
78+
}
79+
80+
[Fact]
81+
public void SetOrder_Id_1_Y_2_called()
82+
{
83+
var cm = new BsonClassMap<C>();
84+
cm.AutoMap();
85+
cm.GetMemberMap("Id").SetOrder(1);
86+
cm.GetMemberMap("Y").SetOrder(2);
87+
cm.Freeze();
88+
89+
cm.AllMemberMaps.Select(m => m.MemberName).Should().Equal("Id", "Y", "X");
90+
}
91+
92+
[Fact]
93+
public void SetOrder_Id_2_X_1_called()
94+
{
95+
var cm = new BsonClassMap<C>();
96+
cm.AutoMap();
97+
cm.GetMemberMap("Id").SetOrder(2);
98+
cm.GetMemberMap("X").SetOrder(1);
99+
cm.Freeze();
100+
101+
cm.AllMemberMaps.Select(m => m.MemberName).Should().Equal("X", "Id", "Y");
102+
}
103+
104+
[Fact]
105+
public void SetOrder_Id_2_Y_1_called()
106+
{
107+
var cm = new BsonClassMap<C>();
108+
cm.AutoMap();
109+
cm.GetMemberMap("Id").SetOrder(2);
110+
cm.GetMemberMap("Y").SetOrder(1);
111+
cm.Freeze();
112+
113+
cm.AllMemberMaps.Select(m => m.MemberName).Should().Equal("Y", "Id", "X");
114+
}
115+
116+
[Fact]
117+
public void SetOrder_X_2_Y_1_called()
118+
{
119+
var cm = new BsonClassMap<C>();
120+
cm.AutoMap();
121+
cm.GetMemberMap("X").SetOrder(2);
122+
cm.GetMemberMap("Y").SetOrder(1);
123+
cm.Freeze();
124+
125+
cm.AllMemberMaps.Select(m => m.MemberName).Should().Equal("Y", "X", "Id");
126+
}
127+
128+
[Fact]
129+
public void SetOrder_Id_1_X_3_Y_2_called()
130+
{
131+
var cm = new BsonClassMap<C>();
132+
cm.AutoMap();
133+
cm.GetMemberMap("Id").SetOrder(1);
134+
cm.GetMemberMap("X").SetOrder(3);
135+
cm.GetMemberMap("Y").SetOrder(2);
136+
cm.Freeze();
137+
138+
cm.AllMemberMaps.Select(m => m.MemberName).Should().Equal("Id", "Y", "X");
139+
}
140+
141+
// nested types
142+
public class C
143+
{
144+
public int Id { get; set; }
145+
public int X { get; set; }
146+
public int Y { get; set; }
147+
}
148+
}
149+
}

0 commit comments

Comments
 (0)