/// <summary>
        /// Define a subdocument (or a list of) as a reference
        /// </summary>
        public EntityBuilder <T> DbRef <K>(Expression <Func <T, K> > property, string collectionName)
        {
            if (string.IsNullOrEmpty(collectionName))
            {
                throw new ArgumentNullException("collectionName");
            }

            return(this.GetProperty(property, (p) =>
            {
                var typeRef = typeof(K);

                if (Reflection.IsList(typeRef))
                {
                    var itemType = typeRef.IsArray ? typeRef.GetElementType() : Reflection.UnderlyingTypeOf(typeRef);
                    var mapper = _mapper.GetPropertyMapper(itemType);

                    RegisterDbRefList(p, collectionName, typeRef, itemType, mapper);
                }
                else
                {
                    var mapper = _mapper.GetPropertyMapper(typeRef);

                    RegisterDbRef(p, collectionName, typeRef, mapper);
                }
            }));
        }
Beispiel #2
0
        internal object Deserialize(Type type, BsonValue value)
        {
            Func <BsonValue, object> custom;

            // null value - null returns
            if (value.IsNull)
            {
                return(null);
            }

            // if is nullable, get underlying type
            else if (Reflection.IsNullable(type))
            {
                type = Reflection.UnderlyingTypeOf(type);
            }

            // check if your type is already a BsonValue/BsonDocument/BsonArray
            if (type == typeof(BsonValue))
            {
                return(new BsonValue(value));
            }
            else if (type == typeof(BsonDocument))
            {
                return(value.AsDocument);
            }
            else if (type == typeof(BsonArray))
            {
                return(value.AsArray);
            }

            // raw values to native bson values
            else if (_bsonTypes.Contains(type))
            {
                return(value.RawValue);
            }

            // simple ConvertTo to basic .NET types
            else if (_basicTypes.Contains(type))
            {
                return(Convert.ChangeType(value.RawValue, type));
            }

            // enum value is a string
            else if (type.IsEnum)
            {
                return(Enum.Parse(type, value.AsString));
            }

            // test if has a custom type implementation
            else if (_customDeserializer.TryGetValue(type, out custom))
            {
                return(custom(value));
            }

            // if value is array, deserialize as array
            else if (value.IsArray)
            {
                if (type.IsArray)
                {
                    return(this.DeserializeArray(type.GetElementType(), value.AsArray));
                }
                else
                {
                    return(this.DeserializeList(type, value.AsArray));
                }
            }

            // if value is document, deserialize as document
            else if (value.IsDocument)
            {
                BsonValue typeField;
                var       doc = value.AsDocument;

                // test if value is object and has _type
                if (doc.RawValue.TryGetValue("_type", out typeField))
                {
                    type = Type.GetType(typeField.AsString);
                }

                var o = Reflection.CreateInstance(type);

                if (o is IDictionary && type.IsGenericType)
                {
                    var k = type.GetGenericArguments()[0];
                    var t = type.GetGenericArguments()[1];

                    this.DeserializeDictionary(k, t, (IDictionary)o, value.AsDocument);
                }
                else
                {
                    this.DeserializeObject(type, o, doc);
                }

                return(o);
            }

            // in last case, return value as-is - can cause "cast error"
            // it's used for "public object MyInt { get; set; }"
            return(value.RawValue);
        }