Skip to content

Commit 6317b7a

Browse files
committed
added support for upcasting in linq.
1 parent ddf2e90 commit 6317b7a

File tree

3 files changed

+108
-9
lines changed

3 files changed

+108
-9
lines changed

Driver/Linq/Utils/BsonSerializationInfoHelper.cs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,7 @@ public BsonSerializationInfo GetSerializationInfo(Expression expression)
6969
_serializerCache[parameterExpression] = serializer;
7070
}
7171

72-
return new BsonSerializationInfo(
73-
null, // elementName
74-
serializer,
75-
parameterExpression.Type, // nominalType
76-
null); // serialization options
72+
return GetSerializationInfo(serializer, expression);
7773
}
7874

7975
parameterExpression = ExpressionParameterFinder.FindParameter(expression);
@@ -170,11 +166,24 @@ public BsonArray SerializeValues(BsonSerializationInfo serializationInfo, IEnume
170166

171167
private BsonSerializationInfo GetSerializationInfo(IBsonSerializer serializer, Expression expression)
172168
{
173-
// when looking to get a member's serialization info, we will ignore a top-level return conversion because
174-
// it is inconsequential
169+
var parameterExpression = expression as ParameterExpression;
170+
if (parameterExpression != null)
171+
{
172+
return new BsonSerializationInfo(
173+
null,
174+
serializer,
175+
parameterExpression.Type,
176+
null);
177+
}
178+
175179
if (expression.NodeType == ExpressionType.Convert || expression.NodeType == ExpressionType.ConvertChecked)
176180
{
177-
return GetSerializationInfo(serializer, ((UnaryExpression)expression).Operand);
181+
var conversionSerializer = serializer;
182+
183+
//if the operand can be assigned from the expression, than we are upcasting and need to get the more specific serializer
184+
if (((UnaryExpression)expression).Operand.Type.IsAssignableFrom(expression.Type))
185+
conversionSerializer = BsonSerializer.LookupSerializer(expression.Type);
186+
return GetSerializationInfo(conversionSerializer, ((UnaryExpression)expression).Operand);
178187
}
179188

180189
var memberExpression = expression as MemberExpression;
@@ -316,8 +325,11 @@ private BsonSerializationInfo GetSerializationInfoMember(IBsonSerializer seriali
316325
if (memberSerializationInfoProvider != null)
317326
{
318327
var memberSerializationInfo = memberSerializationInfoProvider.GetMemberSerializationInfo(memberName);
328+
var elementName = memberSerializationInfo.ElementName;
329+
if (!string.IsNullOrEmpty(containingSerializationInfo.ElementName))
330+
elementName = containingSerializationInfo.ElementName + "." + elementName;
319331
return new BsonSerializationInfo(
320-
containingSerializationInfo.ElementName + "." + memberSerializationInfo.ElementName,
332+
elementName,
321333
memberSerializationInfo.Serializer,
322334
memberSerializationInfo.NominalType,
323335
memberSerializationInfo.SerializationOptions);

DriverUnitTests/DriverUnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@
164164
<Compile Include="Jira\CSharp365Tests.cs" />
165165
<Compile Include="Jira\CSharp378Tests.cs" />
166166
<Compile Include="Jira\CSharp418Tests.cs" />
167+
<Compile Include="Jira\CSharp471Tests.cs" />
167168
<Compile Include="Jira\CSharp77Tests.cs" />
168169
<Compile Include="Jira\CSharp92Tests.cs" />
169170
<Compile Include="Jira\CSharp93Tests.cs" />
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/* Copyright 2010-2012 10gen 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.IO;
19+
using System.Linq;
20+
using System.Runtime.Serialization;
21+
using System.Text;
22+
using NUnit.Framework;
23+
24+
using MongoDB.Driver;
25+
using MongoDB.Driver.Linq;
26+
27+
namespace MongoDB.DriverUnitTests.Jira
28+
{
29+
[TestFixture]
30+
public class CSharp471Tests
31+
{
32+
public class Base
33+
{
34+
public Guid Id { get; set; }
35+
36+
public string A { get; set; }
37+
}
38+
39+
public class T1 : Base
40+
{
41+
public string B { get; set; }
42+
}
43+
44+
public class T2 : Base
45+
{
46+
public string C { get; set; }
47+
}
48+
49+
[Test]
50+
public void CastTest()
51+
{
52+
var server = MongoServer.Create();
53+
var db = server.GetDatabase("test");
54+
var collection = db.GetCollection<Base>("castTest");
55+
collection.Drop();
56+
57+
var t1 = new T1 { Id = Guid.NewGuid(), A = "T1.A", B = "T1.B" };
58+
var t2 = new T2 { Id = Guid.NewGuid(), A = "T2.A" };
59+
collection.Insert(t1);
60+
collection.Insert(t2);
61+
62+
var query = from t in collection.AsQueryable()
63+
where t is T1 && ((T1)t).B == "T1.B"
64+
select t;
65+
66+
var translatedQuery = MongoQueryTranslator.Translate(query);
67+
Assert.IsInstanceOf<SelectQuery>(translatedQuery);
68+
Assert.AreSame(collection, translatedQuery.Collection);
69+
Assert.AreSame(typeof(Base), translatedQuery.DocumentType);
70+
71+
var selectQuery = (SelectQuery)translatedQuery;
72+
Assert.AreEqual("(Base t) => ((t is T1) && ((T1)t.B == \"T1.B\"))", ExpressionFormatter.ToString(selectQuery.Where));
73+
Assert.IsNull(selectQuery.OrderBy);
74+
Assert.IsNull(selectQuery.Projection);
75+
Assert.IsNull(selectQuery.Skip);
76+
Assert.IsNull(selectQuery.Take);
77+
78+
Assert.AreEqual("{ \"_t\" : \"T1\", \"B\" : \"T1.B\" }", selectQuery.BuildQuery().ToString());
79+
80+
var results = query.ToList();
81+
Assert.That(results.Count, Is.EqualTo(1));
82+
Assert.That(results[0], Is.InstanceOf(typeof(T1)));
83+
Assert.That(results[0].A, Is.EqualTo("T1.A"));
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)