-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
DowncastingSerializer.cs
130 lines (113 loc) · 4.91 KB
/
DowncastingSerializer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* Copyright 2010-present MongoDB Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
namespace MongoDB.Bson.Serialization.Serializers
{
/// <summary>
/// An interface implemented by DowncastingSerializer.
/// </summary>
public interface IDowncastingSerializer
{
/// <summary>
/// The base type that the serializer will downcast from.
/// </summary>
Type BaseType { get; }
/// <summary>
/// The serializer for the derived type.
/// </summary>
IBsonSerializer DerivedSerializer { get; }
/// <summary>
/// The derived type that the serializer will downcast to.
/// </summary>
Type DerivedType { get; }
}
/// <summary>
/// Static factory class for DowncastingSerializer.
/// </summary>
public static class DowncastingSerializer
{
/// <summary>
/// Creates a new DowncastingSerializer.
/// </summary>
/// <param name="baseType">The base type.</param>
/// <param name="derivedType">The derived type.</param>
/// <param name="derivedTypeSerializer">The derived type serializer.</param>
/// <returns>A <see cref="DowncastingSerializer"/> instance.</returns>
public static IBsonSerializer Create(
Type baseType,
Type derivedType,
IBsonSerializer derivedTypeSerializer)
{
var downcastingSerializerType = typeof(DowncastingSerializer<,>).MakeGenericType(baseType, derivedType);
return (IBsonSerializer)Activator.CreateInstance(downcastingSerializerType, derivedTypeSerializer);
}
}
/// <summary>
/// A serializer for TBase where the actual values are of type TDerived.
/// </summary>
/// <typeparam name="TBase">The base type.</typeparam>
/// <typeparam name="TDerived">The derived type.</typeparam>
public class DowncastingSerializer<TBase, TDerived> : SerializerBase<TBase>, IBsonArraySerializer, IBsonDocumentSerializer, IDowncastingSerializer
where TDerived : TBase
{
private readonly IBsonSerializer<TDerived> _derivedSerializer;
/// <summary>
/// Initializes a new instance of DowncastingSerializer.
/// </summary>
/// <param name="derivedSerializer">The derived type serializer.</param>
/// <exception cref="ArgumentNullException"></exception>
public DowncastingSerializer(IBsonSerializer<TDerived> derivedSerializer)
{
_derivedSerializer = derivedSerializer ?? throw new ArgumentNullException(nameof(derivedSerializer));
}
/// <inheritdoc/>
public Type BaseType => typeof(TBase);
/// <summary>
/// The serializer for the derived type.
/// </summary>
public IBsonSerializer<TDerived> DerivedSerializer => _derivedSerializer;
IBsonSerializer IDowncastingSerializer.DerivedSerializer => _derivedSerializer;
/// <inheritdoc/>
public Type DerivedType => typeof(TDerived);
/// <inheritdoc/>
public override TBase Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
return _derivedSerializer.Deserialize(context);
}
/// <inheritdoc/>
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TBase value)
{
_derivedSerializer.Serialize(context, (TDerived)value);
}
/// <inheritdoc/>
public bool TryGetItemSerializationInfo(out BsonSerializationInfo serializationInfo)
{
if (_derivedSerializer is IBsonArraySerializer arraySerializer)
{
return arraySerializer.TryGetItemSerializationInfo(out serializationInfo);
}
throw new InvalidOperationException($"The class {_derivedSerializer.GetType().FullName} does not implement IBsonArraySerializer.");
}
/// <inheritdoc/>
public bool TryGetMemberSerializationInfo(string memberName, out BsonSerializationInfo serializationInfo)
{
if (_derivedSerializer is IBsonDocumentSerializer documentSerializer)
{
return documentSerializer.TryGetMemberSerializationInfo(memberName, out serializationInfo);
}
throw new InvalidOperationException($"The class {_derivedSerializer.GetType().FullName} does not implement IBsonDocumentSerializer.");
}
}
}