Skip to content

Commit 5e117c1

Browse files
committed
Work in progress.
1 parent 1577d3c commit 5e117c1

File tree

6 files changed

+197
-10
lines changed

6 files changed

+197
-10
lines changed

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,20 @@ namespace MongoDB.Bson.Serialization.Serializers
2323
/// </summary>
2424
public interface IKeyValuePairSerializer
2525
{
26+
/// <summary>
27+
///
28+
/// </summary>
29+
IBsonSerializer KeySerializer { get; }
30+
2631
/// <summary>
2732
/// Gets the representation.
2833
/// </summary>
2934
BsonType Representation { get; }
35+
36+
/// <summary>
37+
///
38+
/// </summary>
39+
IBsonSerializer ValueSerializer { get; }
3040
}
3141

3242
/// <summary>
@@ -145,6 +155,8 @@ public IBsonSerializer<TKey> KeySerializer
145155
get { return _lazyKeySerializer.Value; }
146156
}
147157

158+
IBsonSerializer IKeyValuePairSerializer.KeySerializer => KeySerializer;
159+
148160
/// <summary>
149161
/// Gets the representation.
150162
/// </summary>
@@ -167,6 +179,8 @@ public IBsonSerializer<TValue> ValueSerializer
167179
get { return _lazyValueSerializer.Value; }
168180
}
169181

182+
IBsonSerializer IKeyValuePairSerializer.ValueSerializer => ValueSerializer;
183+
170184
// public methods
171185
/// <summary>
172186
/// Deserializes a value.

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,33 @@ void DeduceCoshMethodSerializers()
16011601

16021602
void DeduceCreateMethodSerializers()
16031603
{
1604+
#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
1605+
if (method.Is(KeyValuePairMethod.Create))
1606+
{
1607+
if (AnyAreNotKnown(arguments) && IsKnown(node, out var nodeSerializer))
1608+
{
1609+
var keyExpression = arguments[0];
1610+
var valueExpression = arguments[1];
1611+
1612+
if (nodeSerializer is IKeyValuePairSerializer keyValuePairSerializer)
1613+
{
1614+
var keySerializer = keyValuePairSerializer.KeySerializer;
1615+
var valueSerializer = keyValuePairSerializer.ValueSerializer;
1616+
DeduceSerializer(keyExpression, keySerializer);
1617+
DeduceSerializer(valueExpression, valueSerializer);
1618+
}
1619+
}
1620+
1621+
if (IsNotKnown(node) && AllAreKnown(arguments, out var argumentSerializers))
1622+
{
1623+
var keySerializer = argumentSerializers[0];
1624+
var valueSerializer = argumentSerializers[1];
1625+
var keyValuePairSerializer = KeyValuePairSerializer.Create(BsonType.Document, keySerializer, valueSerializer);
1626+
AddKnownSerializer(node, keyValuePairSerializer);
1627+
}
1628+
}
1629+
else
1630+
#endif
16041631
if (method.IsOneOf(__tupleOrValueTupleCreateMethods))
16051632
{
16061633
if (AnyAreNotKnown(arguments) && IsKnown(node, out var nodeSerializer))

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

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

16+
using System;
1617
using System.Linq;
1718
using System.Linq.Expressions;
1819
using System.Reflection;
@@ -35,15 +36,7 @@ protected override Expression VisitNew(NewExpression node)
3536
if (IsKnown(node, out var nodeSerializer) &&
3637
arguments.Any(IsNotKnown))
3738
{
38-
if (constructor == BsonDocumentConstructor.WithNameAndValue)
39-
{
40-
var nameExpression = arguments[0];
41-
var valueExpression = arguments[1];
42-
DeduceStringSerializer(nameExpression);
43-
DeduceBsonValueSerializer(valueExpression);
44-
DeduceBsonDocumentSerializer(node);
45-
}
46-
else
39+
if (nodeSerializer is IBsonDocumentSerializer)
4740
{
4841
var matchingMemberSerializationInfos = nodeSerializer.GetMatchingMemberSerializationInfosForConstructorParameters(node, node.Constructor);
4942
for (var i = 0; i < matchingMemberSerializationInfos.Count; i++)
@@ -75,10 +68,37 @@ protected override Expression VisitNew(NewExpression node)
7568

7669
IBsonSerializer GetKnownSerializer(ConstructorInfo constructor)
7770
{
78-
if (constructor == BsonDocumentConstructor.WithNoParameters || constructor == BsonDocumentConstructor.WithNameAndValue)
71+
if (constructor.DeclaringType == typeof(BsonDocument))
7972
{
8073
return BsonDocumentSerializer.Instance;
8174
}
75+
else if (constructor.DeclaringType == typeof(BsonValue))
76+
{
77+
return BsonValueSerializer.Instance;
78+
}
79+
else if (constructor.DeclaringType == typeof(DateTime))
80+
{
81+
return DateTimeSerializer.Instance;
82+
}
83+
else if (DictionaryConstructor.IsWithIEnumerableKeyValuePairConstructor(constructor))
84+
{
85+
var collectionExpression = arguments[0];
86+
if (IsItemSerializerKnown(collectionExpression, out var itemSerializer) &&
87+
itemSerializer is IKeyValuePairSerializer keyValuePairSerializer)
88+
{
89+
var keySerializer = keyValuePairSerializer.KeySerializer;
90+
var valueSerializer = keyValuePairSerializer.ValueSerializer;
91+
return DictionarySerializer.Create(keySerializer, valueSerializer);
92+
}
93+
}
94+
else if (HashSetConstructor.IsWithCollectionConstructor(constructor))
95+
{
96+
var collectionExpression = arguments[0];
97+
if (IsItemSerializerKnown(collectionExpression, out var itemSerializer))
98+
{
99+
return HashSetSerializer.Create(itemSerializer);
100+
}
101+
}
82102
else if (ListConstructor.IsWithCollectionConstructor(constructor))
83103
{
84104
var collectionExpression = arguments[0];
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* Copyright 2010-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 System.Collections.Generic;
17+
using System.Reflection;
18+
using MongoDB.Driver.Linq.Linq3Implementation.Misc;
19+
20+
namespace MongoDB.Driver.Linq.Linq3Implementation.Reflection
21+
{
22+
internal static class HashSetConstructor
23+
{
24+
public static bool IsWithCollectionConstructor(ConstructorInfo constructor)
25+
{
26+
if (constructor != null)
27+
{
28+
var declaringType = constructor.DeclaringType;
29+
var parameters = constructor.GetParameters();
30+
return
31+
declaringType.IsConstructedGenericType &&
32+
declaringType.GetGenericTypeDefinition() == typeof(HashSet<>) &&
33+
parameters.Length == 1 &&
34+
parameters[0].ParameterType.ImplementsIEnumerable(out var itemType) &&
35+
itemType == declaringType.GenericTypeArguments[0];
36+
}
37+
38+
return false;
39+
}
40+
}
41+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* Copyright 2010-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 System;
17+
using System.Collections.Generic;
18+
using MongoDB.Bson.Serialization;
19+
using MongoDB.Bson.Serialization.Options;
20+
using MongoDB.Bson.Serialization.Serializers;
21+
22+
namespace MongoDB.Driver.Linq.Linq3Implementation.Serializers;
23+
24+
internal static class DictionarySerializer
25+
{
26+
public static IBsonSerializer Create(IBsonSerializer keySerializer, IBsonSerializer valueSerializer)
27+
{
28+
var serializerType = typeof(DictionarySerializer<,>).MakeGenericType(keySerializer.ValueType, valueSerializer.ValueType);
29+
return (IBsonSerializer)Activator.CreateInstance(serializerType, keySerializer, valueSerializer);
30+
}
31+
}
32+
33+
internal class DictionarySerializer<TKey, TValue> : DictionaryInterfaceImplementerSerializer<Dictionary<TKey, TValue>, TKey, TValue>
34+
{
35+
public DictionarySerializer(IBsonSerializer<TKey> keySerializer, IBsonSerializer<TValue> valueSerializer)
36+
: base(DictionaryRepresentation.Document, keySerializer, valueSerializer)
37+
{
38+
}
39+
40+
protected override ICollection<KeyValuePair<TKey, TValue>> CreateAccumulator() => new Dictionary<TKey, TValue>();
41+
42+
protected override Dictionary<TKey, TValue>FinalizeAccumulator(ICollection<KeyValuePair<TKey, TValue>> accumulator) => (Dictionary<TKey, TValue>)accumulator;
43+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* Copyright 2010-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 System;
17+
using System.Collections.Generic;
18+
using MongoDB.Bson.Serialization;
19+
using MongoDB.Bson.Serialization.Serializers;
20+
21+
namespace MongoDB.Driver.Linq.Linq3Implementation.Serializers;
22+
23+
internal static class HashSetSerializer
24+
{
25+
public static IBsonSerializer Create(IBsonSerializer itemSerializer)
26+
{
27+
var serializerType = typeof(HashSetSerializer<>).MakeGenericType(itemSerializer.ValueType);
28+
return (IBsonSerializer)Activator.CreateInstance(serializerType, itemSerializer);
29+
}
30+
}
31+
32+
internal class HashSetSerializer<T> : EnumerableInterfaceImplementerSerializerBase<HashSet<T>, T>
33+
{
34+
public HashSetSerializer(IBsonSerializer<T> itemSerializer)
35+
: base(itemSerializer)
36+
{
37+
}
38+
39+
protected override object CreateAccumulator() => new HashSet<T>();
40+
41+
protected override HashSet<T> FinalizeResult(object accumulator) => (HashSet<T>)accumulator;
42+
}

0 commit comments

Comments
 (0)