Skip to content

Commit 56a464c

Browse files
committed
CSHARP-5572: Refactoring ready for review.
1 parent 8970838 commit 56a464c

21 files changed

+208
-503
lines changed

src/MongoDB.Bson/Serialization/IBsonSerializerExtensions.cs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,19 @@ public static TValue Deserialize<TValue>(this IBsonSerializer<TValue> serializer
5353
/// <summary>
5454
/// Gets the serializer for a base type starting from a serializer for a derived type.
5555
/// </summary>
56-
/// <param name="serializer">The serializer for the derived type.</param>
56+
/// <param name="derivedTypeSerializer">The serializer for the derived type.</param>
5757
/// <param name="baseType">The base type.</param>
5858
/// <returns>The serializer for the base type.</returns>
59-
public static IBsonSerializer GetBaseTypeSerializer(this IBsonSerializer serializer, Type baseType)
59+
public static IBsonSerializer GetBaseTypeSerializer(this IBsonSerializer derivedTypeSerializer, Type baseType)
6060
{
61-
if (!baseType.IsAssignableFrom(serializer.ValueType))
61+
if (derivedTypeSerializer.ValueType == baseType)
6262
{
63-
throw new ArgumentException($"{baseType} is not assignable from {serializer.ValueType}.");
63+
return derivedTypeSerializer;
64+
}
65+
66+
if (!baseType.IsAssignableFrom(derivedTypeSerializer.ValueType))
67+
{
68+
throw new ArgumentException($"{baseType} is not assignable from {derivedTypeSerializer.ValueType}.");
6469
}
6570

6671
return BsonSerializer.LookupSerializer(baseType); // TODO: should be able to navigate from serializer
@@ -69,14 +74,19 @@ public static IBsonSerializer GetBaseTypeSerializer(this IBsonSerializer seriali
6974
/// <summary>
7075
/// Gets the serializer for a derived type starting from a serializer for a base type.
7176
/// </summary>
72-
/// <param name="serializer">The serializer for the base type.</param>
77+
/// <param name="baseTypeSerializer">The serializer for the base type.</param>
7378
/// <param name="derivedType">The derived type.</param>
7479
/// <returns>The serializer for the derived type.</returns>
75-
public static IBsonSerializer GetDerivedTypeSerializer(this IBsonSerializer serializer, Type derivedType)
80+
public static IBsonSerializer GetDerivedTypeSerializer(this IBsonSerializer baseTypeSerializer, Type derivedType)
7681
{
77-
if (!serializer.ValueType.IsAssignableFrom(derivedType))
82+
if (baseTypeSerializer.ValueType == derivedType)
83+
{
84+
return baseTypeSerializer;
85+
}
86+
87+
if (!baseTypeSerializer.ValueType.IsAssignableFrom(derivedType))
7888
{
79-
throw new ArgumentException($"{serializer.ValueType} is not assignable from {derivedType}.");
89+
throw new ArgumentException($"{baseTypeSerializer.ValueType} is not assignable from {derivedType}.");
8090
}
8191

8292
return BsonSerializer.LookupSerializer(derivedType); // TODO: should be able to navigate from serializer

src/MongoDB.Driver/Linq/Linq3Implementation/KnownSerializerFinders/KnownSerializerFinderHelperMethods.cs

Lines changed: 50 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -29,31 +29,26 @@ internal partial class KnownSerializerFinderVisitor
2929
{
3030
private void AddKnownSerializer(Expression node, IBsonSerializer serializer) => _knownSerializers.AddSerializer(node, serializer);
3131

32-
private bool AllAreKnown(IEnumerable<Expression> nodes, out IReadOnlyList<IBsonSerializer> serializers)
32+
private bool AllAreKnown(IEnumerable<Expression> nodes, out IReadOnlyList<IBsonSerializer> knownSerializers)
3333
{
34-
var serializersList = new List<IBsonSerializer>();
34+
var knownSerializersList = new List<IBsonSerializer>();
3535
foreach (var node in nodes)
3636
{
37-
if (IsKnown(node, out var knownSerializer))
37+
if (IsKnown(node, out var nodeSerializer))
3838
{
39-
serializersList.Add(knownSerializer);
39+
knownSerializersList.Add(nodeSerializer);
4040
}
4141
else
4242
{
43-
serializers = null;
43+
knownSerializers = null;
4444
return false;
4545
}
4646
}
4747

48-
serializers = serializersList;
48+
knownSerializers = knownSerializersList;
4949
return true;
5050
}
5151

52-
private bool AnyAreNotKnown(IEnumerable<Expression> nodes)
53-
{
54-
return nodes.Any(IsNotKnown);
55-
}
56-
5752
private bool AnyIsKnown(IEnumerable<Expression> nodes, out IBsonSerializer knownSerializer)
5853
{
5954
foreach (var node in nodes)
@@ -76,19 +71,17 @@ private bool AnyIsNotKnown(IEnumerable<Expression> nodes)
7671

7772
private bool CanDeduceSerializer(Expression node1, Expression node2, out Expression unknownNode, out IBsonSerializer knownSerializer)
7873
{
79-
if (IsKnown(node1, out var node1Serializer) &&
80-
IsNotKnown(node2))
74+
if (IsNotKnown(node1) && IsKnown(node2, out var node2Serializer))
8175
{
82-
unknownNode = node2;
83-
knownSerializer = node1Serializer;
76+
unknownNode = node1;
77+
knownSerializer = node2Serializer;
8478
return true;
8579
}
8680

87-
if (IsNotKnown(node1) &&
88-
IsKnown(node2, out var node2Serializer))
81+
if (IsNotKnown(node2) && IsKnown(node1, out var node1Serializer))
8982
{
90-
unknownNode = node1;
91-
knownSerializer = node2Serializer;
83+
unknownNode = node2;
84+
knownSerializer = node1Serializer;
9285
return true;
9386
}
9487

@@ -97,74 +90,75 @@ private bool CanDeduceSerializer(Expression node1, Expression node2, out Express
9790
return false;
9891
}
9992

100-
IBsonSerializer CreateCollectionSerializerFromCollectionSerializer(Type type, IBsonSerializer collectionSerializer)
93+
IBsonSerializer CreateCollectionSerializerFromCollectionSerializer(Type collectionType, IBsonSerializer collectionSerializer)
10194
{
102-
if (collectionSerializer.ValueType == type)
95+
if (collectionSerializer.ValueType == collectionType)
10396
{
10497
return collectionSerializer;
10598
}
10699

100+
if (collectionSerializer is IUnknowableSerializer)
101+
{
102+
return UnknowableSerializer.Create(collectionType);
103+
}
104+
107105
var itemSerializer = collectionSerializer.GetItemSerializer();
108-
return CreateCollectionSerializerFromItemSerializer(type, itemSerializer);
106+
return CreateCollectionSerializerFromItemSerializer(collectionType, itemSerializer);
109107
}
110108

111-
IBsonSerializer CreateCollectionSerializerFromItemSerializer(Type type, IBsonSerializer itemSerializer)
109+
IBsonSerializer CreateCollectionSerializerFromItemSerializer(Type collectionType, IBsonSerializer itemSerializer)
112110
{
113-
return type switch
111+
if (itemSerializer is IUnknowableSerializer)
112+
{
113+
return UnknowableSerializer.Create(collectionType);
114+
}
115+
116+
return collectionType switch
114117
{
115-
_ when type.IsArray => ArraySerializer.Create(itemSerializer),
116-
_ when type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>) => IEnumerableSerializer.Create(itemSerializer),
117-
_ when type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(IOrderedEnumerable<>) => IOrderedEnumerableSerializer.Create(itemSerializer),
118-
_ when type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(IQueryable<>) => IQueryableSerializer.Create(itemSerializer),
119-
_ => (BsonSerializer.LookupSerializer(type) as IChildSerializerConfigurable)?.WithChildSerializer(itemSerializer)
118+
_ when collectionType.IsArray => ArraySerializer.Create(itemSerializer),
119+
_ when collectionType.IsConstructedGenericType && collectionType.GetGenericTypeDefinition() == typeof(IEnumerable<>) => IEnumerableSerializer.Create(itemSerializer),
120+
_ when collectionType.IsConstructedGenericType && collectionType.GetGenericTypeDefinition() == typeof(IOrderedEnumerable<>) => IOrderedEnumerableSerializer.Create(itemSerializer),
121+
_ when collectionType.IsConstructedGenericType && collectionType.GetGenericTypeDefinition() == typeof(IQueryable<>) => IQueryableSerializer.Create(itemSerializer),
122+
_ => (BsonSerializer.LookupSerializer(collectionType) as IChildSerializerConfigurable)?.WithChildSerializer(itemSerializer)
120123
};
121124
}
122125

123-
private void DeduceBooleanSerializer(Expression node)
126+
private void DeduceBaseTypeAndDerivedTypeSerializers(Expression baseTypeExpression, Expression derivedTypeExpression)
124127
{
125-
if (IsNotKnown(node))
128+
if (IsNotKnown(baseTypeExpression) && IsKnown(derivedTypeExpression, out var knownDerivedTypeSerializer))
126129
{
127-
AddKnownSerializer(node, BooleanSerializer.Instance);
130+
var baseTypeSerializer = knownDerivedTypeSerializer.GetBaseTypeSerializer(baseTypeExpression.Type);
131+
AddKnownSerializer(baseTypeExpression, baseTypeSerializer);
128132
}
129-
}
130133

131-
private void DeduceBsonDocumentSerializer(Expression node)
132-
{
133-
if (IsNotKnown(node))
134+
if (IsNotKnown(derivedTypeExpression) && IsKnown(baseTypeExpression, out var knownBaseTypeSerializer))
134135
{
135-
AddKnownSerializer(node, BsonDocumentSerializer.Instance);
136+
var derivedTypeSerializer = knownBaseTypeSerializer.GetDerivedTypeSerializer(baseTypeExpression.Type);
137+
AddKnownSerializer(derivedTypeExpression, derivedTypeSerializer);
136138
}
137139
}
138140

139-
private void DeduceBsonValueSerializer(Expression node)
141+
private void DeduceBooleanSerializer(Expression node)
140142
{
141143
if (IsNotKnown(node))
142144
{
143-
AddKnownSerializer(node, BsonValueSerializer.Instance);
145+
AddKnownSerializer(node, BooleanSerializer.Instance);
144146
}
145147
}
146148

147149
private void DeduceCollectionAndCollectionSerializers(Expression collectionExpression1, Expression collectionExpression2)
148150
{
149-
IBsonSerializer collectionSerializer1;
150-
IBsonSerializer collectionSerializer2;
151-
152-
if (IsNotKnown(collectionExpression1) && IsKnown(collectionExpression2, out collectionSerializer2))
151+
if (IsNotKnown(collectionExpression1) && IsKnown(collectionExpression2, out var knownCollectionSerializer2))
153152
{
154-
collectionSerializer1 = collectionSerializer2 is IUnknowableSerializer ?
155-
UnknowableSerializer.Create(collectionExpression1.Type) :
156-
CreateCollectionSerializerFromCollectionSerializer(collectionExpression1.Type, collectionSerializer2);
153+
var collectionSerializer1 = CreateCollectionSerializerFromCollectionSerializer(collectionExpression1.Type, knownCollectionSerializer2);
157154
AddKnownSerializer(collectionExpression1, collectionSerializer1);
158155
}
159156

160-
if (IsNotKnown(collectionExpression2) && IsKnown(collectionExpression1, out collectionSerializer1))
157+
if (IsNotKnown(collectionExpression2) && IsKnown(collectionExpression1, out var knownCollectionSerializer1))
161158
{
162-
collectionSerializer2 = collectionSerializer1 is IUnknowableSerializer ?
163-
UnknowableSerializer.Create(collectionExpression2.Type) :
164-
CreateCollectionSerializerFromCollectionSerializer(collectionExpression2.Type, collectionSerializer1);
159+
var collectionSerializer2 = CreateCollectionSerializerFromCollectionSerializer(collectionExpression2.Type, knownCollectionSerializer1);
165160
AddKnownSerializer(collectionExpression2, collectionSerializer2);
166161
}
167-
168162
}
169163

170164
private void DeduceCollectionAndItemSerializers(Expression collectionExpression, Expression itemExpression)
@@ -181,9 +175,7 @@ private void DeduceItemAndCollectionSerializers(Expression itemExpression, Expre
181175

182176
if (IsNotKnown(collectionExpression) && IsKnown(itemExpression, out itemSerializer))
183177
{
184-
var collectionSerializer = itemSerializer is IUnknowableSerializer ?
185-
UnknowableSerializer.Create(collectionExpression.Type) :
186-
CreateCollectionSerializerFromItemSerializer(collectionExpression.Type, itemSerializer);
178+
var collectionSerializer = CreateCollectionSerializerFromItemSerializer(collectionExpression.Type, itemSerializer);
187179
if (collectionSerializer != null)
188180
{
189181
AddKnownSerializer(collectionExpression, collectionSerializer);
@@ -201,12 +193,12 @@ private void DeduceSerializer(Expression node, IBsonSerializer serializer)
201193

202194
private void DeduceSerializers(Expression expression1, Expression expression2)
203195
{
204-
if (IsNotKnown(expression1) && IsKnown(expression2, out var expression2Serializer))
196+
if (IsNotKnown(expression1) && IsKnown(expression2, out var expression2Serializer) && expression2Serializer.ValueType == expression1.Type)
205197
{
206198
AddKnownSerializer(expression1, expression2Serializer);
207199
}
208200

209-
if (IsNotKnown(expression2) && IsKnown(expression1, out var expression1Serializer))
201+
if (IsNotKnown(expression2) && IsKnown(expression1, out var expression1Serializer)&& expression1Serializer.ValueType == expression2.Type)
210202
{
211203
AddKnownSerializer(expression2, expression1Serializer);
212204
}
@@ -231,8 +223,8 @@ private void DeduceUnknowableSerializer(Expression node)
231223

232224
private bool IsItemSerializerKnown(Expression node, out IBsonSerializer itemSerializer)
233225
{
234-
if (IsKnown(node, out var serializer) &&
235-
serializer is IBsonArraySerializer arraySerializer &&
226+
if (IsKnown(node, out var nodeSerializer) &&
227+
nodeSerializer is IBsonArraySerializer arraySerializer &&
236228
arraySerializer.TryGetItemSerializationInfo(out var itemSerializationInfo))
237229
{
238230
itemSerializer = itemSerializationInfo.Serializer;

src/MongoDB.Driver/Linq/Linq3Implementation/KnownSerializerFinders/KnownSerializerFinderNewExpressionSerializerCreator.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ public IBsonSerializer CreateNewExpressionSerializer(
5656
{
5757
var creatorMapParameter = creatorMapParameters[i];
5858
var constructorArgumentExpression = constructorArguments[i];
59-
var constructorArgumentType = constructorArgumentExpression.Type;
6059
if (!IsKnown(constructorArgumentExpression, out var constructorArgumentSerializer))
6160
{
6261
return null;

src/MongoDB.Driver/Linq/Linq3Implementation/KnownSerializerFinders/KnownSerializerFinderVisitConditional.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,20 @@ internal partial class KnownSerializerFinderVisitor
2121
{
2222
protected override Expression VisitConditional(ConditionalExpression node)
2323
{
24-
var ifTrue = node.IfTrue;
25-
var ifFalse = node.IfFalse;
26-
27-
DeduceSerializers(ifTrue, node);
28-
DeduceSerializers(ifFalse, node);
24+
var ifTrueExpression = node.IfTrue;
25+
var ifFalseExpression = node.IfFalse;
2926

27+
DeduceConditionaSerializers();
3028
base.VisitConditional(node);
31-
32-
DeduceSerializers(ifTrue, ifFalse);
33-
DeduceSerializers(node, ifTrue);
29+
DeduceConditionaSerializers();
3430

3531
return node;
32+
33+
void DeduceConditionaSerializers()
34+
{
35+
DeduceBaseTypeAndDerivedTypeSerializers(node, ifTrueExpression);
36+
DeduceBaseTypeAndDerivedTypeSerializers(node, ifFalseExpression);
37+
DeduceBaseTypeAndDerivedTypeSerializers(node, ifTrueExpression); // call a second time in case ifFalse is the only known serializer
38+
}
3639
}
3740
}

src/MongoDB.Driver/Linq/Linq3Implementation/KnownSerializerFinders/KnownSerializerFinderVisitConstant.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ protected override Expression VisitConstant(ConstantExpression node)
3131
}
3232
else
3333
{
34-
// constant => node: registeredSerializer
3534
var registeredSerializer = BsonSerializer.LookupSerializer(node.Type); // TODO: don't use static registry
3635
AddKnownSerializer(node, registeredSerializer);
3736
}

src/MongoDB.Driver/Linq/Linq3Implementation/KnownSerializerFinders/KnownSerializerFinderVisitIndex.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ protected override Expression VisitIndex(IndexExpression node)
5454
DeduceSerializer(node, itemSerializer);
5555
}
5656
}
57-
// TODO: Deduce UnknowableSerializer???
5857
// handle generic cases?
5958

6059
return node;

src/MongoDB.Driver/Linq/Linq3Implementation/KnownSerializerFinders/KnownSerializerFinderVisitLambda.cs

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,21 @@
1313
* limitations under the License.
1414
*/
1515

16-
using System;
1716
using System.Linq.Expressions;
17+
using MongoDB.Driver.Linq.Linq3Implementation.Serializers;
1818

1919
namespace MongoDB.Driver.Linq.Linq3Implementation.KnownSerializerFinders;
2020

2121
internal partial class KnownSerializerFinderVisitor
2222
{
2323
protected override Expression VisitLambda<T>(Expression<T> node)
2424
{
25-
base.VisitLambda(node);
25+
if (IsNotKnown(node))
26+
{
27+
var ignoreNodeSerializer = IgnoreNodeSerializer.Create(node.Type);
28+
AddKnownSerializer(node, ignoreNodeSerializer);
29+
}
2630

27-
// var parameters = node.Parameters;
28-
// var body = node.Body;
29-
// if (parameters.Count == 1 &&
30-
// parameters[0] is var parameter &&
31-
// body.Type == parameter.Type &&
32-
// IsKnown(parameter, out var parameterSerializer) &&
33-
// IsNotKnown(body))
34-
// {
35-
// // TODO: remove?
36-
// // _knownSerializers.AddSerializer(body, parameterSerializer);
37-
// throw new Exception("Should not reach here.");
38-
// }
39-
40-
return node;
31+
return base.VisitLambda(node);
4132
}
4233
}

src/MongoDB.Driver/Linq/Linq3Implementation/KnownSerializerFinders/KnownSerializerFinderVisitMethodCall.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,7 +1244,7 @@ void DeduceAppendOrPrependMethodSerializers()
12441244
var elementExpression = arguments[1];
12451245

12461246
DeduceItemAndCollectionSerializers(elementExpression, sourceExpression);
1247-
DeduceSerializers(node, sourceExpression);
1247+
DeduceCollectionAndCollectionSerializers(node, sourceExpression);
12481248
}
12491249
else
12501250
{
@@ -1697,7 +1697,7 @@ void DeduceCreateMethodSerializers()
16971697
#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
16981698
if (method.Is(KeyValuePairMethod.Create))
16991699
{
1700-
if (AnyAreNotKnown(arguments) && IsKnown(node, out var nodeSerializer))
1700+
if (AnyIsNotKnown(arguments) && IsKnown(node, out var nodeSerializer))
17011701
{
17021702
var keyExpression = arguments[0];
17031703
var valueExpression = arguments[1];
@@ -1721,7 +1721,7 @@ void DeduceCreateMethodSerializers()
17211721
#endif
17221722
if (method.IsOneOf(__tupleOrValueTupleCreateMethods))
17231723
{
1724-
if (AnyAreNotKnown(arguments) && IsKnown(node, out var nodeSerializer))
1724+
if (AnyIsNotKnown(arguments) && IsKnown(node, out var nodeSerializer))
17251725
{
17261726
if (nodeSerializer is IBsonTupleSerializer tupleSerializer)
17271727
{

src/MongoDB.Driver/Linq/Linq3Implementation/KnownSerializerFinders/KnownSerializerFinderVisitUnary.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@ void DeduceUnaryOperatorSerializers()
5757
var resultSerializer = unaryOperator switch
5858
{
5959
ExpressionType.ArrayLength => Int32Serializer.Instance,
60-
ExpressionType.Not => StandardSerializers.GetSerializer(node.Type),
6160
ExpressionType.Convert or ExpressionType.TypeAs => GetConvertSerializer(),
61+
ExpressionType.Not => StandardSerializers.GetSerializer(node.Type),
62+
ExpressionType.Quote => IgnoreNodeSerializer.Create(node.Type),
6263
_ => null
6364
};
6465

0 commit comments

Comments
 (0)