Beispiel #1
0
        public BsonMapper(Func <Type, object> customTypeInstantiator = null, ITypeNameBinder typeNameBinder = null)
        {
            this.SerializeNullValues   = false;
            this.TrimWhitespace        = true;
            this.EmptyStringToNull     = true;
            this.ResolveFieldName      = (s) => s;
            this.ResolveMember         = (t, mi, mm) => { };
            this.ResolveCollectionName = (t) => Reflection.IsList(t) ? Reflection.GetListItemType(t).Name : t.Name;
            this.IncludeFields         = false;

            _typeInstantiator = customTypeInstantiator ?? ((Type t) => null);
            _typeNameBinder   = typeNameBinder ?? DefaultTypeNameBinder.Instance;

            #region Register CustomTypes

            RegisterType <Uri>(uri => uri.AbsoluteUri, bson => new Uri(bson.AsString));
            RegisterType <DateTimeOffset>(value => new BsonValue(value.UtcDateTime), bson => bson.AsDateTime.ToUniversalTime());
            RegisterType <TimeSpan>(value => new BsonValue(value.Ticks), bson => new TimeSpan(bson.AsInt64));
            RegisterType <Regex>(
                r => r.Options == RegexOptions.None ? new BsonValue(r.ToString()) : new BsonDocument {
                { "p", r.ToString() }, { "o", (int)r.Options }
            },
                value => value.IsString ? new Regex(value) : new Regex(value.AsDocument["p"].AsString, (RegexOptions)value.AsDocument["o"].AsInt32)
                );


            #endregion
        }
Beispiel #2
0
        /// <summary>
        /// Register a property mapper as DbRef to serialize/deserialize only document reference _id
        /// </summary>
        internal static void RegisterDbRef(BsonMapper mapper, MemberMapper member, ITypeNameBinder typeNameBinder, string collection)
        {
            member.IsDbRef = true;

            if (member.IsEnumerable)
            {
                RegisterDbRefList(mapper, member, typeNameBinder, collection);
            }
            else
            {
                RegisterDbRefItem(mapper, member, typeNameBinder, collection);
            }
        }
Beispiel #3
0
 internal EntityBuilder(BsonMapper mapper, ITypeNameBinder typeNameBinder)
 {
     _mapper         = mapper;
     _typeNameBinder = typeNameBinder;
     _entity         = mapper.GetEntityMapper(typeof(T));
 }
Beispiel #4
0
        /// <summary>
        /// Register a property as a DbRefList - implement a custom Serialize/Deserialize actions to convert entity to $id, $ref only
        /// </summary>
        private static void RegisterDbRefList(BsonMapper mapper, MemberMapper member, ITypeNameBinder typeNameBinder, string collection)
        {
            // get entity from list item type
            var entity = mapper.GetEntityMapper(member.UnderlyingType);

            member.Serialize = (list, m) =>
            {
                // supports null values when "SerializeNullValues = true"
                if (list == null)
                {
                    return(BsonValue.Null);
                }

                var result  = new BsonArray();
                var idField = entity.Id;

                foreach (var item in (IEnumerable)list)
                {
                    if (item == null)
                    {
                        continue;
                    }

                    var id = idField.Getter(item);

                    var bsonDocument = new BsonDocument
                    {
                        ["$id"]  = m.Serialize(id.GetType(), id, 0),
                        ["$ref"] = collection
                    };

                    if (member.UnderlyingType != item.GetType())
                    {
                        bsonDocument["$type"] = typeNameBinder.GetName(item.GetType());
                    }

                    result.Add(bsonDocument);
                }

                return(result);
            };

            member.Deserialize = (bson, m) =>
            {
                if (bson.IsArray == false)
                {
                    return(null);
                }

                var array = bson.AsArray;

                if (array.Count == 0)
                {
                    return(m.Deserialize(member.DataType, array));
                }

                // copy array changing $id to _id
                var result = new BsonArray();

                foreach (var item in array)
                {
                    if (item.IsDocument == false)
                    {
                        continue;
                    }

                    var doc      = item.AsDocument;
                    var idRef    = doc["$id"];
                    var missing  = doc["$missing"] == true;
                    var included = doc.ContainsKey("$ref") == false;

                    // if referece document are missing, do not inlcude on output list
                    if (missing)
                    {
                        continue;
                    }

                    // if refId is null was included by "include" query, so "item" is full filled document
                    if (included)
                    {
                        item["_id"] = idRef;
                        if (item.AsDocument.ContainsKey("$type"))
                        {
                            item["_type"] = item["$type"];
                        }

                        result.Add(item);
                    }
                    else
                    {
                        var bsonDocument = new BsonDocument {
                            ["_id"] = idRef
                        };

                        if (item.AsDocument.ContainsKey("$type"))
                        {
                            bsonDocument["_type"] = item["$type"];
                        }

                        result.Add(bsonDocument);
                    }
                }

                return(m.Deserialize(member.DataType, result));
            };
        }
Beispiel #5
0
        /// <summary>
        /// Register a property as a DbRef - implement a custom Serialize/Deserialize actions to convert entity to $id, $ref only
        /// </summary>
        private static void RegisterDbRefItem(BsonMapper mapper, MemberMapper member, ITypeNameBinder typeNameBinder, string collection)
        {
            // get entity
            var entity = mapper.GetEntityMapper(member.DataType);

            member.Serialize = (obj, m) =>
            {
                // supports null values when "SerializeNullValues = true"
                if (obj == null)
                {
                    return(BsonValue.Null);
                }

                var idField = entity.Id;

                // #768 if using DbRef with interface with no ID mapped
                if (idField == null)
                {
                    throw new LiteException(0, "There is no _id field mapped in your type: " + member.DataType.FullName);
                }

                var id = idField.Getter(obj);

                var bsonDocument = new BsonDocument
                {
                    ["$id"]  = m.Serialize(id.GetType(), id, 0),
                    ["$ref"] = collection
                };

                if (member.DataType != obj.GetType())
                {
                    bsonDocument["$type"] = typeNameBinder.GetName(obj.GetType());
                }

                return(bsonDocument);
            };

            member.Deserialize = (bson, m) =>
            {
                // if not a document (maybe BsonValue.null) returns null
                if (bson == null || bson.IsDocument == false)
                {
                    return(null);
                }

                var doc      = bson.AsDocument;
                var idRef    = doc["$id"];
                var missing  = doc["$missing"] == true;
                var included = doc.ContainsKey("$ref") == false;

                if (missing)
                {
                    return(null);
                }

                if (included)
                {
                    doc["_id"] = idRef;
                    if (doc.ContainsKey("$type"))
                    {
                        doc["_type"] = bson["$type"];
                    }

                    return(m.Deserialize(entity.ForType, doc));
                }
                else
                {
                    return(m.Deserialize(entity.ForType,
                                         doc.ContainsKey("$type") ?
                                         new BsonDocument {
                        ["_id"] = idRef, ["_type"] = bson["$type"]
                    } :
                                         new BsonDocument {
                        ["_id"] = idRef
                    }));                                           // if has $id, deserialize object using only _id object
                }
            };
        }
Beispiel #6
0
        /// <summary>
        /// Register a property as a DbRef - implement a custom Serialize/Deserialize actions to convert entity to $id, $ref only
        /// </summary>
        private static void RegisterDbRefItem(BsonMapper mapper, MemberMapper member, ITypeNameBinder typeNameBinder, string collection)
        {
            // get entity
            var entity = mapper.GetEntityMapper(member.DataType);

            member.Serialize = (obj, m) =>
            {
                // supports null values when "SerializeNullValues = true"
                if (obj == null)
                {
                    return(BsonValue.Null);
                }

                var idField = entity.Id;

                // #768 if using DbRef with interface with no ID mapped
                if (idField == null)
                {
                    throw new LiteException(0, "There is no _id field mapped in your type: " + member.DataType.FullName);
                }

                var id = idField.Getter(obj);

                var bsonDocument = new BsonDocument
                {
                    ["$id"]  = m.Serialize(id.GetType(), id, 0),
                    ["$ref"] = collection
                };

                if (member.DataType != obj.GetType())
                {
                    bsonDocument["$type"] = typeNameBinder.GetName(obj.GetType());
                }

                return(bsonDocument);
            };

            member.Deserialize = (bson, m) =>
            {
                var idRef   = bson.IsDocument ? bson["$id"] : BsonValue.Null;
                var missing = bson.IsDocument ? (bson["$missing"] == true) : false;

                if (missing)
                {
                    return(null);
                }

                return(m.Deserialize(entity.ForType,
                                     idRef.IsNull ?
                                     bson : // if has no $id object was full loaded (via Include) - so deserialize using normal function
                                     bson.AsDocument.ContainsKey("$type") ?
                                     new BsonDocument {
                    ["_id"] = idRef, ["_type"] = bson["$type"]
                } :
                                     new BsonDocument {
                    ["_id"] = idRef
                }));                                           // if has $id, deserialize object using only _id object
            };
        }