-
Notifications
You must be signed in to change notification settings - Fork 1
/
MongoDocument.cs
180 lines (143 loc) · 5.26 KB
/
MongoDocument.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CSMongo.Exceptions;
using CSMongo.Bson;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using CSMongo.IO;
using CSMongo.Types;
using CSMongo.DataTypes;
namespace CSMongo {
/// <summary>
/// A document to use for storage with a MongoDatabase
/// </summary>
public class MongoDocument : BsonDocument {
#region Constructors
/// <summary>
/// Creates an empty MongoDocument with a default ID assigned
/// </summary>
public MongoDocument()
: this(false, null) {
}
/// <summary>
/// Creates an empty MongoDocument with a default ID assigned
/// </summary>
public MongoDocument(object source)
: this(false, source) {
}
/// <summary>
/// Creates an empty MongoDocument with a default ID assigned
/// </summary>
public MongoDocument(bool generateId)
: this(false, null) {
}
/// <summary>
/// Creates a MongoDocument using the provided object as a template
/// </summary>
public MongoDocument(bool generateId, object source)
: base(source) {
if (generateId) { this.GenerateId(); }
}
#endregion
#region Operators
/// <summary>
/// Merges another object with this object - Same as calling Merge
/// </summary>
public static MongoDocument operator +(MongoDocument target, object value) {
target.Merge(value);
return target;
}
/// <summary>
/// Merges another DynamicObject with this object - Same as calling Merge
/// </summary>
public static MongoDocument operator +(MongoDocument target, BsonObject value) {
target.Merge(value);
return target;
}
/// <summary>
/// Removes the field provided - Same as calling Remove
/// </summary>
public static MongoDocument operator -(MongoDocument target, string field) {
target.Remove(field);
return target;
}
/// <summary>
/// Removes the field provided - Same as calling Remove
/// </summary>
public static MongoDocument operator -(MongoDocument target, string[] fields) {
target.Remove(fields);
return target;
}
#endregion
#region Methods
/// <summary>
/// Creates an Oid for this document - MongoDB will
/// automatically create an Oid when needed
/// </summary>
public MongoOid GenerateId() {
this.Id = new MongoOid();
return this.Id;
}
#endregion
#region Properties
/// <summary>
/// The Oid for a document (if any)
/// </summary>
public MongoOid Id {
get {
//if no id has been generated, do it now
MongoOid id = this.Get<MongoOid>(Mongo.DocumentIdKey, null);
if (id == null) {
id = new MongoOid();
this.Set(Mongo.DocumentIdKey, id);
}
//return the id to use
return id;
}
set {
//if trying to assign anything that isn't a MongoOid
//then complain about it
if (value != null && !(value is MongoOid)) {
throw new ArgumentException("You can only assign a MongoOid as the Id for a MongoDocument");
}
//update the value
this.Set<MongoOid>(Mongo.DocumentIdKey, value);
}
}
#endregion
#region Rendering
/// <summary>
/// Handles reordering so that the Oid is at the start
/// </summary>
protected override IEnumerable<BsonFieldDetail> OnBeforeFinishBsonRender(IEnumerable<BsonFieldDetail> fields) {
//convert to a list that can be modified
List<BsonFieldDetail> list = fields.ToList();
//get all of the ids to use
IEnumerable<BsonFieldDetail> ids = fields.Where(item => item.Type is MongoOidType);
list.RemoveAll(item => item.Type is MongoOidType);
list = list.OrderBy(item => item.Length).ToList();
//because the items are shared in the same list
//we have to insert these one at the time since
//if we use AddRange an exception will be thrown
//since the list is modified while enumerating
//through the values. We're also going backwards
//to make sure they retain their original order
for (int index = ids.Count(); index-- > 0; ) {
list.Insert(0, ids.ElementAt(index));
}
//then return the list
return list.AsEnumerable();
}
/// <summary>
/// Handles rendering the bytes required to create this type
/// </summary>
/// <returns></returns>
public override byte[] ToBsonByteArray() {
if (this.Id == null) { this.GenerateId(); }
return base.ToBsonByteArray();
}
#endregion
}
}