Skip to content

Commit 7d49521

Browse files
committed
Lazy inizialization of DiscriminatedInterfaceSerializer
1 parent 31332ea commit 7d49521

File tree

2 files changed

+39
-25
lines changed

2 files changed

+39
-25
lines changed

src/MongoDB.Bson/Serialization/BsonClassMap.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,9 +424,9 @@ internal class FreezeContext
424424
/// <returns>The frozen class map.</returns>
425425
public BsonClassMap Freeze() => Freeze(BsonSerializer.DefaultSerializationDomain);
426426

427-
internal BsonClassMap Freeze(IBsonSerializationDomain domain)
427+
internal BsonClassMap Freeze(IBsonSerializationDomain serializationDomain)
428428
{
429-
var freezeContext = new FreezeContext { SerializationDomain = domain };
429+
var freezeContext = new FreezeContext { SerializationDomain = serializationDomain };
430430
return Freeze(freezeContext);
431431
}
432432

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

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,11 @@ private static IBsonSerializer<TInterface> CreateInterfaceSerializer(IBsonSerial
5555

5656
// private fields
5757
private readonly Type _interfaceType;
58-
private readonly IDiscriminatorConvention _discriminatorConvention;
5958
private readonly IBsonSerializer<TInterface> _interfaceSerializer;
60-
private readonly IBsonSerializer<object> _objectSerializer;
59+
private readonly Lazy<IDiscriminatorConvention> _discriminatorConvention;
60+
private readonly Lazy<IBsonSerializer<object>> _objectSerializer;
61+
62+
private IBsonSerializationDomain _serializationDomain;
6163

6264
// constructors
6365
/// <summary>
@@ -109,26 +111,13 @@ public DiscriminatedInterfaceSerializer(IDiscriminatorConvention discriminatorCo
109111
}
110112

111113
_interfaceType = typeof(TInterface);
112-
_discriminatorConvention = discriminatorConvention ?? interfaceSerializer.GetDiscriminatorConvention(); //QUESTION What do we do here? We don't have the domain close by, should we lazy initialize it during serialization/deserialization?
114+
_discriminatorConvention = discriminatorConvention != null
115+
? new Lazy<IDiscriminatorConvention>(() => discriminatorConvention)
116+
: new Lazy<IDiscriminatorConvention>(() => GetDiscriminatorConvention(_serializationDomain));
117+
_objectSerializer = objectSerializer != null
118+
? new Lazy<IBsonSerializer<object>>(() => objectSerializer)
119+
: new Lazy<IBsonSerializer<object>>(() => GetObjectSerializer(_serializationDomain));
113120
_interfaceSerializer = interfaceSerializer;
114-
115-
if (objectSerializer == null)
116-
{
117-
objectSerializer = BsonSerializer.LookupSerializer<object>(); //QUESTION What do we do here? We don't have the domain close by, should we lazy initialize it during serialization/deserialization?
118-
if (objectSerializer is ObjectSerializer standardObjectSerializer)
119-
{
120-
Func<Type, bool> allowedTypes = (Type type) => typeof(TInterface).IsAssignableFrom(type);
121-
objectSerializer = standardObjectSerializer
122-
.WithDiscriminatorConvention(_discriminatorConvention)
123-
.WithAllowedTypes(allowedTypes, allowedTypes);
124-
}
125-
else
126-
{
127-
throw new BsonSerializationException("Can't set discriminator convention on custom object serializer.");
128-
}
129-
}
130-
131-
_objectSerializer = objectSerializer;
132121
}
133122

134123
// public properties
@@ -149,6 +138,7 @@ public DiscriminatedInterfaceSerializer(IDiscriminatorConvention discriminatorCo
149138
/// <exception cref="System.FormatException"></exception>
150139
public override TInterface Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
151140
{
141+
_serializationDomain = context.SerializationDomain;
152142
var bsonReader = context.Reader;
153143

154144
if (bsonReader.GetCurrentBsonType() == BsonType.Null)
@@ -158,7 +148,7 @@ public override TInterface Deserialize(BsonDeserializationContext context, BsonD
158148
}
159149
else
160150
{
161-
var actualType = _discriminatorConvention.GetActualTypeInternal(bsonReader, typeof(TInterface), context.SerializationDomain);
151+
var actualType = _discriminatorConvention.Value.GetActualTypeInternal(bsonReader, typeof(TInterface), context.SerializationDomain);
162152
if (actualType == _interfaceType)
163153
{
164154
var message = string.Format("Unable to determine actual type of object to deserialize for interface type {0}.", _interfaceType.FullName);
@@ -193,6 +183,7 @@ obj is DiscriminatedInterfaceSerializer<TInterface> other &&
193183
/// <param name="value">The document.</param>
194184
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TInterface value)
195185
{
186+
_serializationDomain = context.SerializationDomain;
196187
var bsonWriter = context.Writer;
197188

198189
if (value == null)
@@ -202,7 +193,7 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati
202193
else
203194
{
204195
args.NominalType = typeof(object);
205-
_objectSerializer.Serialize(context, args, value);
196+
_objectSerializer.Value.Serialize(context, args, value);
206197
}
207198
}
208199

@@ -217,5 +208,28 @@ public bool TryGetMemberSerializationInfo(string memberName, out BsonSerializati
217208
serializationInfo = null;
218209
return false;
219210
}
211+
212+
private IDiscriminatorConvention GetDiscriminatorConvention(IBsonSerializationDomain serializationDomain)
213+
{
214+
return _interfaceSerializer.GetDiscriminatorConvention(serializationDomain);
215+
}
216+
217+
private IBsonSerializer<object> GetObjectSerializer(IBsonSerializationDomain serializationDomain)
218+
{
219+
var objectSerializer = serializationDomain.LookupSerializer<object>();
220+
if (objectSerializer is ObjectSerializer standardObjectSerializer)
221+
{
222+
var allowedTypes = (Type type) => typeof(TInterface).IsAssignableFrom(type);
223+
objectSerializer = standardObjectSerializer
224+
.WithDiscriminatorConvention(_discriminatorConvention.Value)
225+
.WithAllowedTypes(allowedTypes, allowedTypes);
226+
}
227+
else
228+
{
229+
throw new BsonSerializationException("Can't set discriminator convention on custom object serializer.");
230+
}
231+
232+
return objectSerializer;
233+
}
220234
}
221235
}

0 commit comments

Comments
 (0)