Skip to content

Commit 391093a

Browse files
author
rstam
committed
CSHARP-767: Support a default value creator so that we can safely support default values of mutable classes.
1 parent faa179b commit 391093a

File tree

3 files changed

+91
-2
lines changed

3 files changed

+91
-2
lines changed

MongoDB.Bson/Serialization/BsonMemberMap.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public class BsonMemberMap
4848
private bool _ignoreIfDefault;
4949
private bool _ignoreIfNull;
5050
private object _defaultValue;
51+
private Func<object> _defaultValueCreator;
5152
private bool _defaultValueSpecified;
5253

5354
// constructors
@@ -221,7 +222,7 @@ public bool IgnoreIfNull
221222
/// </summary>
222223
public object DefaultValue
223224
{
224-
get { return _defaultValue; }
225+
get { return _defaultValueCreator != null ? _defaultValueCreator() : _defaultValue; }
225226
}
226227

227228
/// <summary>
@@ -261,7 +262,7 @@ public void ApplyDefaultValue(object obj)
261262
{
262263
if (_defaultValueSpecified)
263264
{
264-
this.Setter(obj, _defaultValue);
265+
this.Setter(obj, DefaultValue);
265266
}
266267
}
267268

@@ -315,6 +316,7 @@ public BsonMemberMap Reset()
315316
if (_frozen) { ThrowFrozenException(); }
316317

317318
_defaultValue = GetDefaultValue(_memberType);
319+
_defaultValueCreator = null;
318320
_defaultValueSpecified = false;
319321
_elementName = _memberInfo.Name;
320322
_idGenerator = null;
@@ -329,6 +331,19 @@ public BsonMemberMap Reset()
329331
return this;
330332
}
331333

334+
/// <summary>
335+
/// Sets the default value creator.
336+
/// </summary>
337+
/// <param name="defaultValueCreator">The default value creator.</param>
338+
/// <returns>The member map.</returns>
339+
public BsonMemberMap SetDefaultValue(Func<object> defaultValueCreator)
340+
{
341+
_defaultValue = defaultValueCreator(); // need an instance to compare against
342+
_defaultValueCreator = defaultValueCreator;
343+
_defaultValueSpecified = true;
344+
return this;
345+
}
346+
332347
/// <summary>
333348
/// Sets the default value.
334349
/// </summary>
@@ -338,6 +353,7 @@ public BsonMemberMap SetDefaultValue(object defaultValue)
338353
{
339354
if (_frozen) { ThrowFrozenException(); }
340355
_defaultValue = defaultValue;
356+
_defaultValueCreator = null;
341357
_defaultValueSpecified = true;
342358
return this;
343359
}

MongoDB.BsonUnitTests/MongoDB.BsonUnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
<Compile Include="Serialization\Attributes\BsonRepresentationAttributeTests.cs" />
9797
<Compile Include="Serialization\BsonClassMapAutoMappingTests.cs" />
9898
<Compile Include="Serialization\BsonClassMapTests.cs" />
99+
<Compile Include="Serialization\BsonMemberMapDefaultValueCreatorTests.cs" />
99100
<Compile Include="Serialization\BsonMemberMapTests.cs" />
100101
<Compile Include="Serialization\Conventions\AttributeConventionPackTests.cs" />
101102
<Compile Include="Serialization\Conventions\CamelCaseElementNameConventionsTests.cs" />
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* Copyright 2010-2013 10gen 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.Collections.Generic;
17+
using MongoDB.Bson.Serialization;
18+
using NUnit.Framework;
19+
20+
namespace MongoDB.BsonUnitTests.Serialization
21+
{
22+
[TestFixture]
23+
public class BsonMemberMapDefaultValueCreatorTests
24+
{
25+
private class C
26+
{
27+
public int Id { get; set; }
28+
public List<int> L { get; set; }
29+
}
30+
31+
static BsonMemberMapDefaultValueCreatorTests()
32+
{
33+
BsonClassMap.RegisterClassMap<C>(cm =>
34+
{
35+
cm.AutoMap();
36+
cm.GetMemberMap(c => c.L).SetDefaultValue(() => new List<int>());
37+
});
38+
}
39+
40+
[Test]
41+
public void TestEachDefaultValueIsNewInstance()
42+
{
43+
var json = "{ _id : 1 }";
44+
var c = BsonSerializer.Deserialize<C>(json);
45+
var d = BsonSerializer.Deserialize<C>(json);
46+
Assert.IsNotNull(c.L);
47+
Assert.IsNotNull(d.L);
48+
Assert.AreNotSame(c.L, d.L);
49+
}
50+
51+
[Test]
52+
public void TestValueMissing()
53+
{
54+
var json = "{ _id : 1 }";
55+
var c = BsonSerializer.Deserialize<C>(json);
56+
Assert.AreEqual(1, c.Id);
57+
Assert.IsNotNull(c.L);
58+
Assert.AreEqual(0, c.L.Count);
59+
}
60+
61+
[Test]
62+
public void TestValuePresent()
63+
{
64+
var json = "{ _id : 1, L : [1] }";
65+
var c = BsonSerializer.Deserialize<C>(json);
66+
Assert.AreEqual(1, c.Id);
67+
Assert.IsNotNull(c.L);
68+
Assert.AreEqual(1, c.L.Count);
69+
Assert.AreEqual(1, c.L[0]);
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)