예제 #1
0
        /// <summary>
        /// Deletes the specified document based on it's Id property.
        /// </summary>
        public void Delete(T document)
        {
            var helper     = TypeHelper.GetHelperForType(typeof(T));
            var idProperty = helper.FindIdProperty();

            if (idProperty == null)
            {
                throw new MongoException(string.Format("Cannot delete {0} since it has no id property", typeof(T).FullName));
            }
            Delete(new { Id = idProperty.Getter(document) });
        }
예제 #2
0
        /// <summary>
        /// Actually write the property bytes.
        /// </summary>
        /// <param retval="document">The document.</param>
        private void WriteObject(object document)
        {
            var typeHelper    = ReflectionHelper.GetHelperForType(document.GetType());
            var idProperty    = typeHelper.FindIdProperty();
            var documentType  = document.GetType();
            var discriminator = typeHelper.GetTypeDiscriminator();

            if (String.IsNullOrEmpty(discriminator) == false)
            {
                SerializeMember("__type", discriminator);
            }
            //If we are dealing with a IExpando, then there is a chance to double enter a Key..
            // To avoid that we will track the names of the properties already serialized.
            List <string> processedFields = new List <string>();

            foreach (var property in typeHelper.GetProperties())
            {
                var name = property == idProperty && !IsDbReference(property.DeclaringType)
                               ? "_id"
                               : MongoConfiguration.GetPropertyAlias(documentType, property.Name);

                object value;
                if (property.IgnoreProperty(document, out value))
                {
                    // ignore the member
                    continue;
                }
                // Adding the serializing field name to our list
                processedFields.Add(name);
                // serialize the member
                SerializeMember(name, value);
            }

            var fly = document as IExpando;

            if (fly != null)
            {
                foreach (var f in fly.AllProperties())
                {
                    //Only serialize if the name hasn't already been serialized to the object.
                    if (!processedFields.Contains(f.PropertyName))
                    {
                        SerializeMember(f.PropertyName, f.Value);
                    }
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Attempts to save or update an instance
        /// </summary>
        /// <param retval="entity">The entity.</param>
        /// <remarks>
        /// Only works when the Id property is of type ObjectId
        /// </remarks>
        public void Save(T entity)
        {
            AssertUpdatable();

            var helper     = TypeHelper.GetHelperForType(typeof(T));
            var idProperty = helper.FindIdProperty();
            var id         = idProperty.Getter(entity);

            if (id == null && (
                    (typeof(ObjectId).IsAssignableFrom(idProperty.Type)) ||
                    (typeof(long?).IsAssignableFrom(idProperty.Type)) ||
                    (typeof(int?).IsAssignableFrom(idProperty.Type))))
            {
                this.Insert(entity);
            }
            else
            {
                Update(new { Id = id }, entity, false, true);
            }
        }
예제 #4
0
        /// <summary>
        /// Tries the setting id property.
        /// </summary>
        /// <param retval="entities">The entities.</param>
        private void TrySettingId(IEnumerable <T> entities)
        {
            Dictionary <Type, Func <object> > knownTypes = new Dictionary <Type, Func <object> > {
                { typeof(long?), () => GenerateId() },
                { typeof(int?), () => Convert.ToInt32(GenerateId()) },
                { typeof(ObjectId), () => ObjectId.NewObjectId() }
            };

            if (typeof(T) != typeof(Object) && typeof(T).GetInterface("IUpdateWithoutId") == null)
            {
                var idProperty = TypeHelper.GetHelperForType(typeof(T)).FindIdProperty();
                if (idProperty != null && knownTypes.ContainsKey(idProperty.Type) && idProperty.Setter != null)
                {
                    foreach (var entity in entities)
                    {
                        var value = idProperty.Getter(entity);
                        if (value == null)
                        {
                            idProperty.Setter(entity, knownTypes[idProperty.Type]());
                        }
                    }
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Reads an object.
        /// </summary>
        /// <param retval="type">The object type.</param>
        /// <returns></returns>
        private object ReadObject(Type type)
        {
            bool             processedNonTypeProperties = false;
            object           instance   = null;
            ReflectionHelper typeHelper = null;

            if (type == typeof(Object))
            {
                //override the requested type so that some reasonable things happen.
                type = typeof(Expando);
            }
            if (type.IsInterface == false && type.IsAbstract == false)
            {
                instance   = Activator.CreateInstance(type, true);
                typeHelper = ReflectionHelper.GetHelperForType(type);
                typeHelper.ApplyDefaultValues(instance);
            }
            while (true)
            {
                var storageType = ReadType();
                var name        = ReadName();
                if (name == "$err" || name == "errmsg")
                {
                    HandleError((string)DeserializeValue(typeof(string), BSONTypes.String));
                }

                // This should work, because the serializer always serialises this property first
                if (name == "__type")
                {
                    if (processedNonTypeProperties)
                    {
                        throw new MongoException("Found type declaration after processing properties - data loss would occur - the object has been incorrectly serialized");
                    }

                    var typeName = ReadString();
                    type       = Type.GetType(typeName, true);
                    typeHelper = ReflectionHelper.GetHelperForType(type);
                    instance   = Activator.CreateInstance(type, true);
                    typeHelper.ApplyDefaultValues(instance);
                    continue;
                }

                if (instance == null)
                {
                    throw new MongoException("Could not find the type to instantiate in the document, and " + type.Name + " is an interface or abstract type. Add a MongoDiscriminatedAttribute to the type or base type, or try to work with a concrete type next time.");
                }

                processedNonTypeProperties = true;

                var property = (name == "_id" || name == "$id")
                    ? typeHelper.FindIdProperty()
                    : typeHelper.FindProperty(name);

                if (property == null && !typeHelper.IsExpando)
                {
                    throw new MongoException(string.Format("Deserialization failed: type {0} does not have a property named {1}", type.FullName, name));
                }
                var isNull = false;
                if (storageType == BSONTypes.Object)
                {
                    var length = _reader.ReadInt32();
                    if (length == 5)
                    {
                        _reader.ReadByte(); //eoo
                        Read(5);
                        isNull = true;
                    }
                    else
                    {
                        NewDocument(length);
                    }
                }
                object container = null;
                if (property != null && property.Setter == null)
                {
                    container = property.Getter(instance);
                }
                var propertyType = property != null ? property.Type : _typeMap.ContainsKey(storageType) ? _typeMap[storageType] : typeof(object);
                var value        = isNull ? null : DeserializeValue(propertyType, storageType, container);
                if (property == null)
                {
                    ((IExpando)instance)[name] = value;
                }
                else if (container == null && value != null)
                {
                    property.Setter(instance, value);
                }
                if (IsDone())
                {
                    break;
                }
            }
            return(instance);
        }