Skip to content

Commit 320f583

Browse files
committed
CSHARP-1191: Refactor GridFSFileInfo to derive from BsonDocumentBackedClass so that it will be resilient to any existing files collection documents that might be partially mal-formed.
1 parent f336c51 commit 320f583

File tree

3 files changed

+141
-159
lines changed

3 files changed

+141
-159
lines changed

src/MongoDB.Bson/Serialization/BsonDocumentBackedClass.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
using System;
17+
using System.Collections.Generic;
1718

1819
namespace MongoDB.Bson.Serialization
1920
{
@@ -65,6 +66,31 @@ protected internal BsonDocument BackingDocument
6566
}
6667

6768
// protected methods
69+
/// <summary>
70+
/// Gets the value from the backing document.
71+
/// </summary>
72+
/// <typeparam name="T">The type of the value.</typeparam>
73+
/// <param name="memberName">The member name.</param>
74+
/// <returns>The value.</returns>
75+
protected T GetValue<T>(string memberName)
76+
{
77+
BsonSerializationInfo info;
78+
if (!_serializer.TryGetMemberSerializationInfo(memberName, out info))
79+
{
80+
var message = string.Format("The member {0} does not exist.", memberName);
81+
throw new ArgumentException(message, "memberName");
82+
}
83+
84+
BsonValue bsonValue;
85+
if (!_backingDocument.TryGetValue(info.ElementName, out bsonValue))
86+
{
87+
var message = string.Format("The backing document does not contain an element named '{0}'.", info.ElementName);
88+
throw new KeyNotFoundException(message);
89+
}
90+
91+
return (T)info.DeserializeValue(bsonValue);
92+
}
93+
6894
/// <summary>
6995
/// Gets the value from the backing document.
7096
/// </summary>

src/MongoDB.Driver.GridFS.Tests/GridFSFileInfoTests.cs

Lines changed: 46 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ public void Aliases_should_be_deserialized_correctly(
6060
#pragma warning restore
6161
}
6262

63+
[Test]
64+
public void BackingDocument_get_should_return_the_expected_result()
65+
{
66+
var backingDocument = new BsonDocument("x", 1);
67+
var subject = new GridFSFileInfo(backingDocument);
68+
69+
var result = subject.BackingDocument;
70+
71+
result.Should().BeSameAs(backingDocument);
72+
}
73+
6374
[Test]
6475
public void ChunkSizeBytes_get_should_return_the_expected_result()
6576
{
@@ -84,43 +95,11 @@ public void ChunkSizeBytes_should_be_deserialized_correctly()
8495
[Test]
8596
public void constructor_should_initialize_instance()
8697
{
87-
#pragma warning disable 618
88-
var aliases = new[] { "alias" };
89-
var chunkSizeBytes = 1024;
90-
var contentType = "type";
91-
var extraElements = new BsonDocument();
92-
var filename = "name";
93-
var id = ObjectId.GenerateNewId();
94-
var idAsBsonValue = (BsonValue)id;
95-
var length = 512;
96-
var md5 = "md5";
97-
var metadata = new BsonDocument();
98-
var uploadDateTime = DateTime.UtcNow;
99-
100-
var result = new GridFSFileInfo(
101-
aliases,
102-
chunkSizeBytes,
103-
contentType,
104-
extraElements,
105-
filename,
106-
idAsBsonValue,
107-
length,
108-
md5,
109-
metadata,
110-
uploadDateTime);
111-
112-
result.Aliases.Should().BeSameAs(aliases);
113-
result.ChunkSizeBytes.Should().Be(chunkSizeBytes);
114-
result.ContentType.Should().Be(contentType);
115-
result.ExtraElements.Should().Be(extraElements);
116-
result.Filename.Should().Be(filename);
117-
result.Id.Should().Be(id);
118-
result.IdAsBsonValue.Should().Be(idAsBsonValue);
119-
result.Length.Should().Be(length);
120-
result.MD5.Should().Be(md5);
121-
result.Metadata.Should().Be(metadata);
122-
result.UploadDateTime.Should().Be(uploadDateTime);
123-
#pragma warning restore
98+
var backdocument = new BsonDocument();
99+
100+
var result = new GridFSFileInfo(backdocument);
101+
102+
result.BackingDocument.Should().BeSameAs(backdocument);
124103
}
125104

126105
[Test]
@@ -154,40 +133,28 @@ public void ContentType_should_be_deserialized_correctly(
154133
#pragma warning restore
155134
}
156135

157-
[Test]
158-
public void ExtraElements_get_should_return_the_expected_result()
159-
{
160-
var value = new BsonDocument("x", 1);
161-
var subject = CreateSubject(extraElements: value);
162-
163-
var result = subject.ExtraElements;
164-
165-
result.Should().Be(value);
166-
}
167-
168136
[Test]
169137
public void ExtraElements_should_be_deserialized_correctly(
170-
[Values(null, new[] { "x" }, new[] { "x", "y" }, new[] { "ExtraElements" })]
138+
[Values(new string[0], new[] { "x" }, new[] { "x", "y" }, new[] { "ExtraElements" })]
171139
string[] names)
172140
{
173141
var document = CreateFilesCollectionDocument();
174142

175-
BsonDocument extraElements = null;
176-
if (names != null)
143+
var extraElements = new BsonDocument();
144+
var value = 1;
145+
foreach (var name in names)
177146
{
178-
extraElements = new BsonDocument();
179-
var value = 1;
180-
foreach (var name in names)
181-
{
182-
extraElements.Add(name, value++);
183-
}
184-
185-
document.Merge(extraElements);
147+
extraElements.Add(name, value++);
186148
}
187149

150+
document.Merge(extraElements, overwriteExistingElements: false);
151+
188152
var subject = DeserializeFilesCollectionDocument(document);
189153

190-
subject.ExtraElements.Should().Be(extraElements);
154+
foreach (var element in extraElements)
155+
{
156+
subject.BackingDocument[element.Name].Should().Be(element.Value);
157+
}
191158
}
192159

193160
[Test]
@@ -346,7 +313,7 @@ public void Metadata_should_be_deserialized_correctly(
346313
[Test]
347314
public void UploadDateTime_get_should_return_the_expected_result()
348315
{
349-
var value = DateTime.UtcNow;
316+
var value = (new BsonDateTime(DateTime.UtcNow)).ToUniversalTime(); // truncated to millisecond precision
350317
var subject = CreateSubject(uploadDateTime: value);
351318

352319
var result = subject.UploadDateTime;
@@ -390,17 +357,24 @@ private GridFSFileInfo CreateSubject(
390357
BsonDocument metadata = null,
391358
DateTime? uploadDateTime = null)
392359
{
393-
return new GridFSFileInfo(
394-
aliases,
395-
chunkSizeBytes ?? 255 * 1024,
396-
contentType,
397-
extraElements,
398-
filename ?? "name",
399-
idAsBsonValue ?? (BsonValue)ObjectId.GenerateNewId(),
400-
length ?? 0,
401-
md5 ?? "md5",
402-
metadata,
403-
uploadDateTime ?? DateTime.UtcNow);
360+
var backingDocument = new BsonDocument
361+
{
362+
{ "_id", idAsBsonValue ?? (BsonValue)ObjectId.GenerateNewId() },
363+
{ "length", length ?? 0 },
364+
{ "chunkSize", chunkSizeBytes ?? 255 * 1024 },
365+
{ "uploadDate", uploadDateTime ?? DateTime.UtcNow },
366+
{ "md5", md5 ?? "md5" },
367+
{ "filename", filename ?? "filename" },
368+
{ "contentType", contentType, contentType != null },
369+
{ "aliases", () => new BsonArray(aliases.Select(a => new BsonString(a))), aliases != null },
370+
{ "metadata", metadata, metadata != null }
371+
};
372+
if (extraElements != null)
373+
{
374+
backingDocument.Merge(extraElements, overwriteExistingElements: false);
375+
}
376+
377+
return new GridFSFileInfo(backingDocument);
404378
}
405379

406380
private GridFSFileInfo DeserializeFilesCollectionDocument(BsonDocument document)

0 commit comments

Comments
 (0)