internal BsonValue Serialize(Type type, object obj, int depth) { if (++depth > MAX_DEPTH) { throw LiteException.DocumentMaxDepth(MAX_DEPTH, type); } if (obj == null) { return(BsonValue.Null); } // if is already a bson value if (obj is BsonValue bsonValue) { return(bsonValue); } // test string - mapper has some special options else if (obj is String) { var str = this.TrimWhitespace ? (obj as String).Trim() : (String)obj; if (this.EmptyStringToNull && str.Length == 0) { return(BsonValue.Null); } else { return(new BsonValue(str)); } } // basic Bson data types (cast datatype for better performance optimization) else if (obj is Int32) { return(new BsonValue((Int32)obj)); } else if (obj is Int64) { return(new BsonValue((Int64)obj)); } else if (obj is Double) { return(new BsonValue((Double)obj)); } else if (obj is Decimal) { return(new BsonValue((Decimal)obj)); } else if (obj is Byte[]) { return(new BsonValue((Byte[])obj)); } else if (obj is ObjectId) { return(new BsonValue((ObjectId)obj)); } else if (obj is Guid) { return(new BsonValue((Guid)obj)); } else if (obj is Boolean) { return(new BsonValue((Boolean)obj)); } else if (obj is DateTime) { return(new BsonValue((DateTime)obj)); } // basic .net type to convert to bson else if (obj is Int16 || obj is UInt16 || obj is Byte || obj is SByte) { return(new BsonValue(Convert.ToInt32(obj))); } else if (obj is UInt32) { return(new BsonValue(Convert.ToInt64(obj))); } else if (obj is UInt64) { var ulng = ((UInt64)obj); var lng = unchecked ((Int64)ulng); return(new BsonValue(lng)); } else if (obj is Single) { return(new BsonValue(Convert.ToDouble(obj))); } else if (obj is Char) { return(new BsonValue(obj.ToString())); } else if (obj is Enum) { if (this.EnumAsInteger) { return(new BsonValue((int)obj)); } else { return(new BsonValue(obj.ToString())); } } // check if is a custom type else if (_customSerializer.TryGetValue(type, out var custom) || _customSerializer.TryGetValue(obj.GetType(), out custom)) { return(custom(obj)); } // for dictionary else if (obj is IDictionary dict) { // when you are converting Dictionary<string, object> if (type == typeof(object)) { type = obj.GetType(); } var itemType = type.GetTypeInfo().IsGenericType ? type.GetGenericArguments()[1] : typeof(object); return(this.SerializeDictionary(itemType, dict, depth)); } // check if is a list or array else if (obj is IEnumerable) { return(this.SerializeArray(Reflection.GetListItemType(obj.GetType()), obj as IEnumerable, depth)); } // otherwise serialize as a plain object else { return(this.SerializeObject(type, obj, depth)); } }
/// <summary> /// Use this method to override how your class can be, by default, mapped from entity to Bson document. /// Returns an EntityMapper from each requested Type /// </summary> protected virtual EntityMapper BuildEntityMapper(Type type) { var mapper = new EntityMapper(type); var idAttr = typeof(BsonIdAttribute); var ignoreAttr = typeof(BsonIgnoreAttribute); var fieldAttr = typeof(BsonFieldAttribute); var dbrefAttr = typeof(BsonRefAttribute); var members = this.GetTypeMembers(type); var id = this.GetIdMember(members); foreach (var memberInfo in members) { // checks [BsonIgnore] if (memberInfo.IsDefined(ignoreAttr, true)) { continue; } // checks field name conversion var name = this.ResolveFieldName(memberInfo.Name); // check if property has [BsonField] var field = (BsonFieldAttribute)memberInfo.GetCustomAttributes(fieldAttr, false).FirstOrDefault(); // check if property has [BsonField] with a custom field name if (field != null && field.Name != null) { name = field.Name; } // checks if memberInfo is id field if (memberInfo == id) { name = "_id"; } // create getter/setter function var getter = Reflection.CreateGenericGetter(type, memberInfo); var setter = Reflection.CreateGenericSetter(type, memberInfo); // check if property has [BsonId] to get with was setted AutoId = true var autoId = (BsonIdAttribute)memberInfo.GetCustomAttributes(idAttr, false).FirstOrDefault(); // get data type var dataType = memberInfo is PropertyInfo ? (memberInfo as PropertyInfo).PropertyType : (memberInfo as FieldInfo).FieldType; // check if datatype is list/array var isList = Reflection.IsList(dataType); // create a property mapper var member = new MemberMapper { AutoId = autoId == null ? true : autoId.AutoId, FieldName = name, MemberName = memberInfo.Name, DataType = dataType, IsList = isList, UnderlyingType = isList ? Reflection.GetListItemType(dataType) : dataType, Getter = getter, Setter = setter }; // check if property has [BsonRef] var dbRef = (BsonRefAttribute)memberInfo.GetCustomAttributes(dbrefAttr, false).FirstOrDefault(); if (dbRef != null && memberInfo is PropertyInfo) { BsonMapper.RegisterDbRef(this, member, _typeNameBinder, dbRef.Collection ?? this.ResolveCollectionName((memberInfo as PropertyInfo).PropertyType)); } // support callback to user modify member mapper this.ResolveMember?.Invoke(type, memberInfo, member); // test if has name and there is no duplicate field if (member.FieldName != null && mapper.Members.Any(x => x.FieldName.Equals(name, StringComparison.InvariantCultureIgnoreCase)) == false) { mapper.Members.Add(member); } } return(mapper); }