public void ApplyMapping(IEntityDefinition definition, BsonClassMap classMap)
        {
            var entityType = definition.EntityType;

            if (EntityMapping.IsValidTypeToMap(entityType.BaseType))
            {
                EntityMapping.TryRegisterType(entityType.BaseType, out _);
            }
            else
            {
                classMap.SetIsRootClass(true);
            }
        }
        public void ApplyMapping(IEntityDefinition definition, BsonClassMap classMap)
        {
            var entityType = definition.EntityType;
            var properties = definition.Properties;

            foreach (var property in properties)
            {
                var propertyType = property.PropertyType;
                propertyType = propertyType.GetEnumerableItemTypeOrDefault();

                //Maps the property type for handling property nesting
                if (propertyType != entityType && EntityMapping.IsValidTypeToMap(propertyType))
                {
                    EntityMapping.TryRegisterType(propertyType, out _);
                }
            }
        }
Exemple #3
0
        public static UpdateDefinition <TEntity> Set <TEntity>(this UpdateDefinition <TEntity> definition, string fieldName, BsonValue value) where TEntity : class
        {
            var dotNetValue = BsonTypeMapper.MapToDotNetValue(value);
            var valueType   = dotNetValue?.GetType();

            IEntityProperty propertyDefinition = null;

            if (EntityMapping.IsValidTypeToMap(typeof(TEntity)))
            {
                propertyDefinition = EntityMapping.GetOrCreateDefinition(typeof(TEntity))
                                     .TraverseProperties()
                                     .Where(p => p.FullPath == fieldName)
                                     .FirstOrDefault();
            }

            var propertyType = propertyDefinition?.PropertyType;

            if (valueType == null && propertyType == null)
            {
                //For null values - they don't have any type data associated
                valueType = typeof(object);
            }
            else if (valueType == null || (propertyType != null && valueType != propertyType))
            {
                //Where BsonTypeMapper can't determine the type or it is a mismatch to what is set in the entity definition
                //The preference is on the definition type and the serializer on the specific member
                valueType = propertyType;

                //We will need the serializer defined for the specific member
                //Not all serializers will be registered (eg. EntityNavigationSerializer) so we need to look it up manually
                var declaringClassMap = BsonClassMap.LookupClassMap(propertyDefinition.EntityType);
                var memberMap         = declaringClassMap.GetMemberMapForElement(propertyDefinition.ElementName);
                var serializer        = memberMap.GetSerializer();

                //To prevent re-serializing back to a string, we use the BsonDocumentReader over JsonReader
                //Using BsonDocumentReader means the root must be a BsonDocument. Because the value may be a BsonArray, we need to wrap the value.
                var containerDocument = new BsonDocument
                {
                    { "Value", value }
                };

                using (var reader = new BsonDocumentReader(containerDocument))
                {
                    //Get the reader into a state where the serializer is starting on the right element
                    reader.ReadBsonType();
                    reader.ReadStartDocument();
                    reader.ReadBsonType();
                    reader.SkipName();

                    var context = BsonDeserializationContext.CreateRoot(reader);
                    dotNetValue = serializer.Deserialize(context);
                }
            }

            var typeArgs = new[] { typeof(TEntity), valueType };

            var specificDefinitionType = typeof(StringFieldDefinition <,>).MakeGenericType(typeArgs);
            var specificDefinition     = Activator.CreateInstance(specificDefinitionType, fieldName, null);         //ie. StringFieldDefintion<TEntity, valueType>

            foreach (var method in typeof(UpdateDefinitionExtensions).GetMethods(BindingFlags.NonPublic | BindingFlags.Static))
            {
                if (method.Name == nameof(InternalSet))
                {
                    var internalSetMethod = method.MakeGenericMethod(typeArgs);
                    var result            = internalSetMethod.Invoke(null, new[] { definition, specificDefinition, dotNetValue });
                    return(result as UpdateDefinition <TEntity>);
                }
            }

            return(default);