Skip to content

Commit bb5910c

Browse files
committed
CSHARP-1131, CSHARP1132: added support for expression tress in projections and groupings for find and aggregate.
1 parent c7feb5c commit bb5910c

36 files changed

+3587
-37
lines changed

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

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,6 @@ namespace MongoDB.Bson.Tests.Serialization
2929
[TestFixture]
3030
public class BsonSerializerTests
3131
{
32-
[Test]
33-
public void TestAnonymousClass()
34-
{
35-
var obj = new
36-
{
37-
I = 1,
38-
D = 1.1,
39-
S = "Hello"
40-
};
41-
var json = obj.ToJson();
42-
var expected = "{ 'I' : 1, 'D' : 1.1, 'S' : 'Hello' }".Replace("'", "\"");
43-
Assert.AreEqual(expected, json);
44-
45-
var bson = obj.ToBson();
46-
Assert.Throws<InvalidOperationException>(() => BsonSerializer.Deserialize(bson, obj.GetType()));
47-
}
48-
4932
public class Employee
5033
{
5134
private class DateOfBirthSerializer : StructSerializerBase<DateTime>

src/MongoDB.Bson/MongoDB.Bson.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@
212212
<Compile Include="Serialization\Serializers\BsonBinaryDataSerializer.cs" />
213213
<Compile Include="Serialization\Serializers\BsonBooleanSerializer.cs" />
214214
<Compile Include="Serialization\IBsonSerializerExtensions.cs" />
215+
<Compile Include="Serialization\Serializers\ProjectingDeserializer.cs" />
215216
<Compile Include="Serialization\Serializers\SerializerHelper.cs" />
216217
<Compile Include="Serialization\Serializers\DiscriminatedWrapperSerializer.cs" />
217218
<Compile Include="Serialization\Serializers\SerializerBase.cs" />

src/MongoDB.Bson/Serialization/BsonSerializationInfo.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,33 @@ public object DeserializeValue(BsonValue value)
8787
}
8888
}
8989

90+
/// <summary>
91+
/// Merges the new BsonSerializationInfo by taking its properties and concatenating its ElementName.
92+
/// </summary>
93+
/// <param name="newSerializationInfo">The new info.</param>
94+
/// <returns>A new BsonSerializationInfo.</returns>
95+
public BsonSerializationInfo Merge(BsonSerializationInfo newSerializationInfo)
96+
{
97+
string elementName = null;
98+
if (_elementName != null && newSerializationInfo._elementName != null)
99+
{
100+
elementName = _elementName + "." + newSerializationInfo._elementName;
101+
}
102+
else if (_elementName != null)
103+
{
104+
elementName = _elementName;
105+
}
106+
else if (newSerializationInfo._elementName != null)
107+
{
108+
elementName = newSerializationInfo._elementName;
109+
}
110+
111+
return new BsonSerializationInfo(
112+
elementName,
113+
newSerializationInfo._serializer,
114+
newSerializationInfo._nominalType);
115+
}
116+
90117
/// <summary>
91118
/// Serializes the value.
92119
/// </summary>
@@ -130,5 +157,18 @@ public BsonArray SerializeValues(IEnumerable values)
130157
return tempDocument[0].AsBsonArray;
131158
}
132159
}
160+
161+
/// <summary>
162+
/// Creates a new BsonSerializationInfo object using the elementName provided and copying all other attributes.
163+
/// </summary>
164+
/// <param name="elementName">Name of the element.</param>
165+
/// <returns>A new BsonSerializationInfo.</returns>
166+
public BsonSerializationInfo WithNewName(string elementName)
167+
{
168+
return new BsonSerializationInfo(
169+
elementName,
170+
_serializer,
171+
_nominalType);
172+
}
133173
}
134174
}

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,6 @@ public override TClass Deserialize(BsonDeserializationContext context, BsonDeser
7676
throw new BsonSerializationException(message);
7777
}
7878

79-
if (_classMap.IsAnonymous)
80-
{
81-
throw new InvalidOperationException("An anonymous class cannot be deserialized.");
82-
}
83-
8479
if (bsonReader.GetCurrentBsonType() == Bson.BsonType.Null)
8580
{
8681
bsonReader.ReadNull();
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* Copyright 2010-2014 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 System.Linq;
19+
using System.Text;
20+
using System.Threading.Tasks;
21+
using MongoDB.Bson.Serialization;
22+
using MongoDB.Bson.Serialization.Serializers;
23+
24+
namespace MongoDB.Bson.Serialization.Serializers
25+
{
26+
/// <summary>
27+
/// Wraps a serializer and projects using a function.
28+
/// </summary>
29+
/// <typeparam name="TFrom">The type of from.</typeparam>
30+
/// <typeparam name="TTo">The type of to.</typeparam>
31+
public class ProjectingDeserializer<TFrom, TTo> : SerializerBase<TTo>
32+
{
33+
// private fields
34+
private readonly IBsonSerializer<TFrom> _fromSerializer;
35+
private readonly Func<TFrom, TTo> _projector;
36+
37+
// constructors
38+
public ProjectingDeserializer(IBsonSerializer<TFrom> fromSerializer, Func<TFrom, TTo> projector)
39+
{
40+
_fromSerializer = fromSerializer;
41+
_projector = projector;
42+
}
43+
44+
/// <summary>
45+
/// Deserializes a value.
46+
/// </summary>
47+
/// <param name="context">The deserialization context.</param>
48+
/// <param name="args">The deserialization args.</param>
49+
/// <returns>
50+
/// The value.
51+
/// </returns>
52+
public override TTo Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
53+
{
54+
var from = _fromSerializer.Deserialize(context);
55+
return _projector(from);
56+
}
57+
}
58+
}

src/MongoDB.Driver.Tests/IAggregateFluentExtensionsTests.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ public void Group_should_generate_the_correct_group_when_a_result_type_is_not_sp
3838
Assert.AreEqual(expectedGroup, subject.Pipeline.Last());
3939
}
4040

41+
[Test]
42+
public void Group_should_generate_the_correct_document_using_expressions()
43+
{
44+
var subject = CreateSubject()
45+
.Group(x => x.Age, g => new { Name = g.Select(x => x.FirstName + " " + x.LastName).First() });
46+
47+
var expectedProject = BsonDocument.Parse("{$group: {_id: '$Age', Name: {'$first': { '$concat': ['$FirstName', ' ', '$LastName']}}}}");
48+
49+
Assert.AreEqual(expectedProject, subject.Pipeline.Last());
50+
}
51+
4152
[Test]
4253
public void Match_should_generate_the_correct_match()
4354
{
@@ -50,7 +61,7 @@ public void Match_should_generate_the_correct_match()
5061
}
5162

5263
[Test]
53-
public void Project_should_generate_the_correct_group_when_a_result_type_is_not_specified()
64+
public void Project_should_generate_the_correct_document_when_a_result_type_is_not_specified()
5465
{
5566
var subject = CreateSubject()
5667
.Project(new { Awesome = "$Tags" });
@@ -60,6 +71,17 @@ public void Project_should_generate_the_correct_group_when_a_result_type_is_not_
6071
Assert.AreEqual(expectedProject, subject.Pipeline.Last());
6172
}
6273

74+
[Test]
75+
public void Project_should_generate_the_correct_document_using_expressions()
76+
{
77+
var subject = CreateSubject()
78+
.Project(x => new { Name = x.FirstName + " " + x.LastName });
79+
80+
var expectedProject = BsonDocument.Parse("{$project: {Name: {'$concat': ['$FirstName', ' ', '$LastName']}, _id: 0}}");
81+
82+
Assert.AreEqual(expectedProject, subject.Pipeline.Last());
83+
}
84+
6385
[Test]
6486
public void SortBy_should_generate_the_correct_sort()
6587
{

src/MongoDB.Driver.Tests/IFindFluentExtensionsTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
using System.Threading;
1717
using MongoDB.Bson;
18+
using MongoDB.Bson.Serialization.Serializers;
19+
using MongoDB.Driver.Linq.Translators;
1820
using NSubstitute;
1921
using NUnit.Framework;
2022

@@ -34,6 +36,18 @@ public void Projection_should_generate_the_correct_fields_when_a_result_type_is_
3436
Assert.AreEqual(expectedProject, subject.Options.Projection);
3537
}
3638

39+
[Test]
40+
public void Projection_should_generate_the_correct_fields_and_assign_the_correct_result_serializer()
41+
{
42+
var subject = CreateSubject()
43+
.Projection(x => x.FirstName + " " + x.LastName);
44+
45+
var expectedProject = BsonDocument.Parse("{FirstName: 1, LastName: 1, _id: 0}");
46+
47+
Assert.AreEqual(expectedProject, subject.Options.Projection);
48+
Assert.IsInstanceOf<ProjectingDeserializer<ProjectedObject, string>>(subject.Options.ResultSerializer);
49+
}
50+
3751
[Test]
3852
public void SortBy_should_generate_the_correct_sort()
3953
{

0 commit comments

Comments
 (0)