Skip to content

Commit 3be268e

Browse files
committed
CSHARP-1891: Fix backward breaking changes in Distinct method.
1 parent 401f2a6 commit 3be268e

File tree

5 files changed

+127
-32
lines changed

5 files changed

+127
-32
lines changed

src/MongoDB.Driver/FieldValueSerializerHelper.cs

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2016 MongoDB Inc.
1+
/* Copyright 2016-2017 MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -95,15 +95,34 @@ public static IBsonSerializer GetSerializerForValueType(IBsonSerializer fieldSer
9595
return (IBsonSerializer)ienumerableSerializerConstructor.Invoke(new object[] { itemSerializer });
9696
}
9797

98-
// otherwise assume that the value can be cast to the right type for the field serializer
99-
var castingSerializerType = typeof(CastingSerializer<,>).MakeGenericType(valueType, fieldType);
100-
var castingSerializerConstructor = castingSerializerType.GetTypeInfo().GetConstructor(new[] { fieldSerializerInterfaceType });
101-
return (IBsonSerializer)castingSerializerConstructor.Invoke(new object[] { fieldSerializer });
98+
// use the item serializer if fieldSerializer is an IBsonArraySerializer of valueType items
99+
IBsonArraySerializer arraySerializer;
100+
if ((arraySerializer = fieldSerializer as IBsonArraySerializer) != null)
101+
{
102+
BsonSerializationInfo itemSerializationInfo;
103+
if (arraySerializer.TryGetItemSerializationInfo(out itemSerializationInfo))
104+
{
105+
if (itemSerializationInfo.Serializer.ValueType == valueType)
106+
{
107+
return itemSerializationInfo.Serializer;
108+
}
109+
}
110+
}
111+
112+
// if we can't return a valid value serializer based on the field serializer return null
113+
return null;
102114
}
103115

104-
public static IBsonSerializer<TValue> GetSerializerForValueType<TField, TValue>(IBsonSerializer<TField> fieldSerializer)
116+
public static IBsonSerializer GetSerializerForValueType(IBsonSerializer fieldSerializer, Type valueType, object value)
105117
{
106-
return (IBsonSerializer<TValue>)GetSerializerForValueType(fieldSerializer, typeof(TValue));
118+
if (!valueType.GetTypeInfo().IsValueType && value == null)
119+
{
120+
return fieldSerializer;
121+
}
122+
else
123+
{
124+
return GetSerializerForValueType(fieldSerializer, valueType);
125+
}
107126
}
108127

109128
// private static methods
@@ -134,21 +153,6 @@ private static IBsonSerializer WithStringRepresentation(IBsonSerializer serializ
134153
}
135154

136155
// nested types
137-
private class CastingSerializer<TFrom, TTo> : SerializerBase<TFrom>
138-
{
139-
private readonly IBsonSerializer<TTo> _serializer;
140-
141-
public CastingSerializer(IBsonSerializer<TTo> serializer)
142-
{
143-
_serializer = serializer;
144-
}
145-
146-
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TFrom value)
147-
{
148-
_serializer.Serialize(context, args, (TTo)(object)value);
149-
}
150-
}
151-
152156
private class EnumConvertingSerializer<TFrom, TTo> : SerializerBase<TFrom>
153157
{
154158
private readonly IBsonSerializer<TTo> _serializer;

src/MongoDB.Driver/Linq/Expressions/ISerializationExpression.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2015-2016 MongoDB Inc.
1+
/* Copyright 2015-2017 MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -49,7 +49,7 @@ public static BsonValue SerializeValue(this ISerializationExpression field, Type
4949
{
5050
Ensure.IsNotNull(field, nameof(field));
5151

52-
var valueSerializer = FieldValueSerializerHelper.GetSerializerForValueType(field.Serializer, valueType);
52+
var valueSerializer = FieldValueSerializerHelper.GetSerializerForValueType(field.Serializer, valueType, value);
5353

5454
var tempDocument = new BsonDocument();
5555
using (var bsonWriter = new BsonDocumentWriter(tempDocument))

src/MongoDB.Driver/Linq/Translators/PredicateTranslator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2015-2016 MongoDB Inc.
1+
/* Copyright 2015-2017 MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -443,7 +443,7 @@ private FilterDefinition<BsonDocument> TranslateComparison(Expression variableEx
443443

444444
var fieldExpression = GetFieldExpression(variableExpression);
445445

446-
var valueSerializer = FieldValueSerializerHelper.GetSerializerForValueType(fieldExpression.Serializer, constantExpression.Type);
446+
var valueSerializer = FieldValueSerializerHelper.GetSerializerForValueType(fieldExpression.Serializer, constantExpression.Type, value);
447447
var serializedValue = valueSerializer.ToBsonValue(value);
448448

449449
switch (operatorType)

src/MongoDB.Shared/GlobalAssemblyInfo.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717

1818
[assembly: AssemblyCompany("MongoDB Inc.")]
1919
[assembly: AssemblyCopyright("Copyright © 2010-2014 MongoDB Inc.")]
20-
[assembly: AssemblyVersion("0.0.*")]
21-
[assembly: AssemblyInformationalVersion("unofficial")]
22-
[assembly: AssemblyFileVersion("0.0.0.0")]
23-
[assembly: AssemblyMetadata("githash", "none")]
24-
[assembly: AssemblyConfiguration("Debug")]
20+
[assembly: AssemblyVersion("2.4.2.11")]
21+
[assembly: AssemblyInformationalVersion("2.4.2-local-0011")]
22+
[assembly: AssemblyFileVersion("2.4.2.11")]
23+
[assembly: AssemblyMetadata("githash", "cf7accd4bd504d33adb74fc49a4ef9cfec499836")]
24+
[assembly: AssemblyConfiguration("Release")]

tests/MongoDB.Driver.Tests/MongoCollectionImplTests.cs

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2010-2016 MongoDB Inc.
1+
/* Copyright 2010-2017 MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323
using FluentAssertions;
2424
using MongoDB.Bson;
2525
using MongoDB.Bson.Serialization;
26+
using MongoDB.Bson.Serialization.Attributes;
2627
using MongoDB.Bson.Serialization.Serializers;
2728
using MongoDB.Bson.TestHelpers.XunitExtensions;
2829
using MongoDB.Driver.Core.Clusters;
@@ -565,6 +566,96 @@ public void Distinct_should_execute_the_DistinctOperation(
565566
operation.ReadConcern.Should().Be(_readConcern);
566567
}
567568

569+
private enum EnumForDistinctWithArrayField { A, B }
570+
571+
private class ClassForDistinctWithArrayField
572+
{
573+
public int Id { get; set; }
574+
[BsonRepresentation(BsonType.String)]
575+
public EnumForDistinctWithArrayField[] A { get; set; }
576+
}
577+
578+
[Theory]
579+
[ParameterAttributeData]
580+
public void Distinct_should_execute_the_DistinctOperation_when_type_parameter_is_array_field_item_type(
581+
[Values(false, true)] bool async)
582+
{
583+
var fieldName = "A";
584+
var filter = new BsonDocument("x", 1);
585+
var options = new DistinctOptions
586+
{
587+
Collation = new Collation("en_US"),
588+
MaxTime = TimeSpan.FromSeconds(20)
589+
};
590+
591+
var subject = CreateSubject<ClassForDistinctWithArrayField>();
592+
593+
if (async)
594+
{
595+
subject.DistinctAsync<EnumForDistinctWithArrayField>(fieldName, filter, options, CancellationToken.None).GetAwaiter().GetResult();
596+
}
597+
else
598+
{
599+
subject.Distinct<EnumForDistinctWithArrayField>(fieldName, filter, options, CancellationToken.None);
600+
}
601+
602+
var call = _operationExecutor.GetReadCall<IAsyncCursor<EnumForDistinctWithArrayField>>();
603+
604+
call.Operation.Should().BeOfType<DistinctOperation<EnumForDistinctWithArrayField>>();
605+
var operation = (DistinctOperation<EnumForDistinctWithArrayField>)call.Operation;
606+
operation.Collation.Should().BeSameAs(options.Collation);
607+
operation.CollectionNamespace.FullName.Should().Be("foo.bar");
608+
operation.FieldName.Should().Be(fieldName);
609+
operation.Filter.Should().Be(filter);
610+
operation.MaxTime.Should().Be(options.MaxTime);
611+
operation.ReadConcern.Should().Be(_readConcern);
612+
613+
var documentSerializer = BsonSerializer.SerializerRegistry.GetSerializer<ClassForDistinctWithArrayField>();
614+
BsonSerializationInfo fieldSerializationInfo;
615+
((IBsonDocumentSerializer)documentSerializer).TryGetMemberSerializationInfo(fieldName, out fieldSerializationInfo).Should().BeTrue();
616+
var fieldSerializer = (ArraySerializer<EnumForDistinctWithArrayField>)fieldSerializationInfo.Serializer;
617+
operation.ValueSerializer.Should().BeSameAs(fieldSerializer.ItemSerializer);
618+
}
619+
620+
[Theory]
621+
[ParameterAttributeData]
622+
public void Distinct_should_execute_the_DistinctOperation_when_type_parameter_is_string_instead_of_ennum(
623+
[Values(false, true)] bool async)
624+
{
625+
var fieldName = "A";
626+
var filter = new BsonDocument("x", 1);
627+
var options = new DistinctOptions
628+
{
629+
Collation = new Collation("en_US"),
630+
MaxTime = TimeSpan.FromSeconds(20)
631+
};
632+
633+
var subject = CreateSubject<ClassForDistinctWithArrayField>();
634+
635+
if (async)
636+
{
637+
subject.DistinctAsync<string>(fieldName, filter, options, CancellationToken.None).GetAwaiter().GetResult();
638+
}
639+
else
640+
{
641+
subject.Distinct<string>(fieldName, filter, options, CancellationToken.None);
642+
}
643+
644+
var call = _operationExecutor.GetReadCall<IAsyncCursor<string>>();
645+
646+
call.Operation.Should().BeOfType<DistinctOperation<string>>();
647+
var operation = (DistinctOperation<string>)call.Operation;
648+
operation.Collation.Should().BeSameAs(options.Collation);
649+
operation.CollectionNamespace.FullName.Should().Be("foo.bar");
650+
operation.FieldName.Should().Be(fieldName);
651+
operation.Filter.Should().Be(filter);
652+
operation.MaxTime.Should().Be(options.MaxTime);
653+
operation.ReadConcern.Should().Be(_readConcern);
654+
655+
var stringSerializer = BsonSerializer.SerializerRegistry.GetSerializer<string>();
656+
operation.ValueSerializer.Should().BeSameAs(stringSerializer);
657+
}
658+
568659
[Theory]
569660
[ParameterAttributeData]
570661
public void Find_should_execute_the_FindOperation(

0 commit comments

Comments
 (0)