Skip to content

Commit e36efc9

Browse files
committed
CSHARP-2138: Support ISupportInitialize when targeting .NET standard 1.5.
1 parent bff931c commit e36efc9

File tree

3 files changed

+198
-7
lines changed

3 files changed

+198
-7
lines changed

src/MongoDB.Bson/Serialization/Serializers/BsonClassMapSerializer.cs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,32 @@ namespace MongoDB.Bson.Serialization
2929
/// <typeparam name="TClass">The type of the class.</typeparam>
3030
public class BsonClassMapSerializer<TClass> : SerializerBase<TClass>, IBsonIdProvider, IBsonDocumentSerializer, IBsonPolymorphicSerializer
3131
{
32+
#if NETSTANDARD1_5
33+
#region static
34+
private static void CheckForISupportInitializeInterface(out MethodInfo beginInitMethodInfo, out MethodInfo endInitMethodInfo)
35+
{
36+
var classTypeInfo = typeof(TClass).GetTypeInfo();
37+
var iSupportInitializeType = classTypeInfo.GetInterface("ISupportInitialize");
38+
if (iSupportInitializeType != null && iSupportInitializeType.FullName == "System.ComponentModel.ISupportInitialize")
39+
{
40+
var iSupportInitializeTypeInfo = iSupportInitializeType.GetTypeInfo();
41+
beginInitMethodInfo = iSupportInitializeTypeInfo.GetMethod("BeginInit");
42+
endInitMethodInfo = iSupportInitializeTypeInfo.GetMethod("EndInit");
43+
return;
44+
}
45+
46+
beginInitMethodInfo = null;
47+
endInitMethodInfo = null;
48+
}
49+
#endregion
50+
#endif
51+
3252
// private fields
3353
private BsonClassMap _classMap;
54+
#if NETSTANDARD1_5
55+
private readonly MethodInfo _beginInitMethodInfo;
56+
private readonly MethodInfo _endInitMethodInfo;
57+
#endif
3458

3559
// constructors
3660
/// <summary>
@@ -54,6 +78,9 @@ public BsonClassMapSerializer(BsonClassMap classMap)
5478
}
5579

5680
_classMap = classMap;
81+
#if NETSTANDARD1_5
82+
CheckForISupportInitializeInterface(out _beginInitMethodInfo, out _endInitMethodInfo);
83+
#endif
5784
}
5885

5986
// public properties
@@ -147,6 +174,12 @@ public TClass DeserializeClass(BsonDeserializationContext context)
147174
{
148175
supportsInitialization.BeginInit();
149176
}
177+
#endif
178+
#if NETSTANDARD1_5
179+
if (_beginInitMethodInfo != null)
180+
{
181+
_beginInitMethodInfo.Invoke(document, new object[0]);
182+
}
150183
#endif
151184
}
152185

@@ -292,7 +325,12 @@ public TClass DeserializeClass(BsonDeserializationContext context)
292325
supportsInitialization.EndInit();
293326
}
294327
#endif
295-
328+
#if NETSTANDARD1_5
329+
if (_endInitMethodInfo != null)
330+
{
331+
_endInitMethodInfo.Invoke(document, new object[0]);
332+
}
333+
#endif
296334
return document;
297335
}
298336
else
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/* Copyright 2019-present 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 FluentAssertions;
17+
using MongoDB.Bson.IO;
18+
using MongoDB.Bson.Serialization;
19+
using Xunit;
20+
21+
namespace MongoDB.Bson.Tests.Serialization
22+
{
23+
public class BsonClassMapSerializerISupportInitializeTests
24+
{
25+
// public methods
26+
[Fact]
27+
public void BeginInit_and_EndInit_should_be_called_when_deserializing_ClassDerivedFromClassImplementingISupportInitialize()
28+
{
29+
var subject = BsonSerializer.LookupSerializer<ClassDerivedFromClassImplementingISupportInitialize>();
30+
using (var reader = new JsonReader("{ }"))
31+
{
32+
var context = BsonDeserializationContext.CreateRoot(reader);
33+
34+
var result = subject.Deserialize(context);
35+
36+
result.BeginInitWasCalled.Should().BeTrue();
37+
result.EndInitWasCalled.Should().BeTrue();
38+
}
39+
}
40+
41+
[Fact]
42+
public void BeginInit_and_EndInit_should_be_called_when_deserializing_ClassDerivedFromClassImplementingISupportInitializeExplicitly()
43+
{
44+
var subject = BsonSerializer.LookupSerializer<ClassDerivedFromClassImplementingISupportInitializeExplicitly>();
45+
using (var reader = new JsonReader("{ }"))
46+
{
47+
var context = BsonDeserializationContext.CreateRoot(reader);
48+
49+
var result = subject.Deserialize(context);
50+
51+
result.BeginInitWasCalled.Should().BeTrue();
52+
result.EndInitWasCalled.Should().BeTrue();
53+
}
54+
}
55+
56+
[Fact]
57+
public void BeginInit_and_EndInit_should_be_called_when_deserializing_ClassImplementingISupportInitialize()
58+
{
59+
var subject = BsonSerializer.LookupSerializer<ClassImplementingISupportInitialize>();
60+
using (var reader = new JsonReader("{ }"))
61+
{
62+
var context = BsonDeserializationContext.CreateRoot(reader);
63+
64+
var result = subject.Deserialize(context);
65+
66+
result.BeginInitWasCalled.Should().BeTrue();
67+
result.EndInitWasCalled.Should().BeTrue();
68+
}
69+
}
70+
71+
[Fact]
72+
public void BeginInit_and_EndInit_should_be_called_when_deserializing_ClassImplementingISupportInitializeExplicitly()
73+
{
74+
var subject = BsonSerializer.LookupSerializer<ClassImplementingISupportInitializeExplicitly>();
75+
using (var reader = new JsonReader("{ }"))
76+
{
77+
var context = BsonDeserializationContext.CreateRoot(reader);
78+
79+
var result = subject.Deserialize(context);
80+
81+
result.BeginInitWasCalled.Should().BeTrue();
82+
result.EndInitWasCalled.Should().BeTrue();
83+
}
84+
}
85+
86+
[Fact]
87+
public void BeginInit_and_EndInit_should_not_be_called_when_deserializing_ClassDerivedFromClassImplementingISupportInitializeInDifferentNamespace()
88+
{
89+
var subject = BsonSerializer.LookupSerializer<ClassDerivedFromClassImplementingISupportInitializeInDifferentNamespace>();
90+
using (var reader = new JsonReader("{ }"))
91+
{
92+
var context = BsonDeserializationContext.CreateRoot(reader);
93+
94+
var result = subject.Deserialize(context);
95+
96+
result.BeginInitWasCalled.Should().BeFalse();
97+
result.EndInitWasCalled.Should().BeFalse();
98+
}
99+
}
100+
101+
[Fact]
102+
public void BeginInit_and_EndInit_should_not_be_called_when_deserializing_ClassImplementingISupportInitializeInDifferentNamespace()
103+
{
104+
var subject = BsonSerializer.LookupSerializer<ClassImplementingISupportInitializeInDifferentNamespace>();
105+
using (var reader = new JsonReader("{ }"))
106+
{
107+
var context = BsonDeserializationContext.CreateRoot(reader);
108+
109+
var result = subject.Deserialize(context);
110+
111+
result.BeginInitWasCalled.Should().BeFalse();
112+
result.EndInitWasCalled.Should().BeFalse();
113+
}
114+
}
115+
116+
// nested classes
117+
public interface ISupportInitialize
118+
{
119+
void BeginInit();
120+
void EndInit();
121+
}
122+
123+
public class ClassImplementingISupportInitialize : System.ComponentModel.ISupportInitialize
124+
{
125+
public bool BeginInitWasCalled { get; set; }
126+
public bool EndInitWasCalled { get; set; }
127+
public void BeginInit() { BeginInitWasCalled = true; }
128+
public void EndInit() { EndInitWasCalled = true; }
129+
}
130+
131+
public class ClassImplementingISupportInitializeExplicitly : System.ComponentModel.ISupportInitialize
132+
{
133+
public bool BeginInitWasCalled { get; set; }
134+
public bool EndInitWasCalled { get; set; }
135+
void System.ComponentModel.ISupportInitialize.BeginInit() { BeginInitWasCalled = true; }
136+
void System.ComponentModel.ISupportInitialize.EndInit() { EndInitWasCalled = true; }
137+
}
138+
139+
public class ClassImplementingISupportInitializeInDifferentNamespace : MongoDB.Bson.Tests.Serialization.BsonClassMapSerializerISupportInitializeTests.ISupportInitialize
140+
{
141+
public bool BeginInitWasCalled { get; set; }
142+
public bool EndInitWasCalled { get; set; }
143+
public void BeginInit() { BeginInitWasCalled = true; }
144+
public void EndInit() { EndInitWasCalled = true; }
145+
}
146+
147+
public class ClassDerivedFromClassImplementingISupportInitialize : ClassImplementingISupportInitialize
148+
{
149+
}
150+
151+
public class ClassDerivedFromClassImplementingISupportInitializeExplicitly : ClassImplementingISupportInitializeExplicitly
152+
{
153+
}
154+
155+
public class ClassDerivedFromClassImplementingISupportInitializeInDifferentNamespace : ClassImplementingISupportInitializeInDifferentNamespace
156+
{
157+
}
158+
}
159+
}

tests/MongoDB.Bson.Tests/Serialization/BsonSerializerTests.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,10 @@ public void TestSerializeOrder()
137137
}
138138

139139
public class InventoryItem
140-
#if NET452
141140
: ISupportInitialize
142-
#endif
143141
{
144142
public int Price { get; set; }
145143

146-
#if NET452
147144
[BsonIgnore]
148145
public bool WasBeginInitCalled;
149146
[BsonIgnore]
@@ -158,7 +155,6 @@ public void EndInit()
158155
{
159156
WasEndInitCalled = true;
160157
}
161-
#endif
162158
}
163159

164160
[Fact]
@@ -170,10 +166,8 @@ public void TestSerializeInventoryItem()
170166
var rehydrated = BsonSerializer.Deserialize<InventoryItem>(bson);
171167

172168
Assert.Equal(42, rehydrated.Price);
173-
#if NET452
174169
Assert.True(rehydrated.WasBeginInitCalled);
175170
Assert.True(rehydrated.WasEndInitCalled);
176-
#endif
177171
}
178172

179173
[BsonKnownTypes(typeof(B), typeof(C))]

0 commit comments

Comments
 (0)