示例#1
0
        /// <summary>
        /// Create an index based in a custom getter value function. Take care if you already data in your collection (will not be work)
        /// </summary>
        public EntityBuilder <T> Index(string name, Func <T, BsonValue> getter, IndexOptions options)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }
            if (getter == null)
            {
                throw new ArgumentNullException("getter");
            }
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
            if (!BsonDocument.IsValidFieldName(name))
            {
                throw new ArgumentException(string.Format("Field '{0}' has an invalid name.", name));
            }

            // add a new property using a custom getter function
            var p = new PropertyMapper();

            p.PropertyName = "__" + name;
            p.FieldName    = name;
            p.Getter       = new GenericGetter((obj) => getter((T)obj));
            p.PropertyType = typeof(BsonValue);
            p.Setter       = null; // readonly field
            p.IndexOptions = options;


            _prop[p.PropertyName] = p;
            return(this);
        }
示例#2
0
        /// <summary>
        /// Read all properties from a type - store in a static cache - exclude: Id and [BsonIgnore]
        /// </summary>
        public static Dictionary <string, PropertyMapper> GetProperties(Type type, Func <string, string> resolvePropertyName)
        {
            var dict   = new Dictionary <string, PropertyMapper>(StringComparer.OrdinalIgnoreCase);
            var id     = GetIdProperty(type);
            var ignore = typeof(BsonIgnoreAttribute);
                                var idAttr = typeof(BsonIdAttribute);
                                var fieldAttr = typeof(BsonFieldAttribute);
                                var indexAttr = typeof(BsonIndexAttribute);

#if PCL || NETSTANDARD
                                var props = type.GetRuntimeProperties();
#else
                                var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
#endif
                                foreach (var prop in props)
            {
                // ignore indexer property
                if (prop.GetIndexParameters().Length > 0)
                {
                    continue;
                }

                // ignore not read/write
                ////if (!prop.CanRead || !prop.CanWrite) continue;
                if (!prop.CanRead)
                {
                    continue;
                }

                // [BsonIgnore]
                if (prop.IsDefined(ignore, false))
                {
                    continue;
                }

                // check if property has [BsonField]
                var bsonField = prop.IsDefined(fieldAttr, false);

                // create getter/setter IL function
                var getter = LitePlatform.Platform.ReflectionHandler.CreateGenericGetter(type, prop, bsonField);
                var setter = LitePlatform.Platform.ReflectionHandler.CreateGenericSetter(type, prop, bsonField);

                // if not getter or setter - no mapping
                if (getter == null)
                {
                    continue;
                }

                if (dict.ContainsKey(prop.Name))
                {
                    // If the property is already in the dictionary, it's probably an override
                    // Keep the first instance added

                    continue;
                }

                var name = id != null && id.Equals(prop) ? "_id" : resolvePropertyName(prop.Name);

                // check if property has [BsonField] with a custom field name
                if (bsonField)
                {
                    var field = (BsonFieldAttribute)prop.GetCustomAttributes(fieldAttr, false).FirstOrDefault();
                    if (field != null && field.Name != null)
                    {
                        name = field.Name;
                    }
                }

                // check if property has [BsonId] to get with was setted AutoId = true
                var autoId = (BsonIdAttribute)prop.GetCustomAttributes(idAttr, false).FirstOrDefault();

                // checks if this proerty has [BsonIndex]
                var index = (BsonIndexAttribute)prop.GetCustomAttributes(indexAttr, false).FirstOrDefault();

                // if is _id field, do not accept index definition
                if (name == "_id")
                {
                    index = null;
                }

                // test if field name is OK (avoid to check in all instances) - do not test internal classes, like DbRef
                if (BsonDocument.IsValidFieldName(name) == false)
                {
                    throw LiteException.InvalidFormat(prop.Name, name);
                }

                // create a property mapper
                var p = new PropertyMapper
                {
                    AutoId       = autoId == null ? true : autoId.AutoId,
                    FieldName    = name,
                    PropertyName = prop.Name,
                    PropertyType = prop.PropertyType,
                    IndexOptions = index == null ? null : index.Options,
                    Getter       = getter,
                    Setter       = setter
                };

                dict.Add(prop.Name, p);
            }

                                return(dict);
        }
示例#3
0
        /// <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
            {
                Members = new List <MemberMapper>(),
                ForType = type
            };

            var idAttr     = typeof(BsonIdAttribute);
            var ignoreAttr = typeof(BsonIgnoreAttribute);
            var fieldAttr  = typeof(BsonFieldAttribute);
            var indexAttr  = typeof(BsonIndexAttribute);
            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";
                }

                // test if field name is OK (avoid to check in all instances) - do not test internal classes, like DbRef
                if (BsonDocument.IsValidFieldName(name) == false)
                {
                    throw LiteException.InvalidFormat(memberInfo.Name);
                }

                // 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, dbRef.Collection ?? this.ResolveCollectionName((memberInfo as PropertyInfo).PropertyType));
                }

                // support callback to user modify member mapper
                if (this.ResolveMember != null)
                {
                    this.ResolveMember(type, memberInfo, member);
                }

                // test if has name and there is no duplicate field
                if (member.FieldName != null && mapper.Members.Any(x => x.FieldName == name) == false)
                {
                    mapper.Members.Add(member);
                }
            }

            return(mapper);
        }
示例#4
0
        /// <summary>
        /// Read all properties from a type - store in a static cache - exclude: Id and [BsonIgnore]
        /// </summary>
        public static Dictionary <string, PropertyMapper> GetProperties(Type type, Func <string, string> resolvePropertyName)
        {
            var dict       = new Dictionary <string, PropertyMapper>();
            var id         = GetIdProperty(type);
            var ignore     = typeof(BsonIgnoreAttribute);
            var idAttr     = typeof(BsonIdAttribute);
            var fieldAttr  = typeof(BsonFieldAttribute);
            var indexAttr  = typeof(BsonIndexAttribute);
            var props      = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            var isInternal = type.Assembly.Equals(typeof(LiteDatabase).Assembly);

            foreach (var prop in props)
            {
                // ignore indexer property
                if (prop.GetIndexParameters().Length > 0)
                {
                    continue;
                }

                // ignore not read/write
                if (!prop.CanRead || !prop.CanWrite)
                {
                    continue;
                }

                // [BsonIgnore]
                if (prop.IsDefined(ignore, false))
                {
                    continue;
                }

                // create getter/setter IL function
                var getter = CreateGetMethod(type, prop);
                var setter = CreateSetMethod(type, prop);

                // if not getter or setter - no mapping
                if (getter == null)
                {
                    continue;
                }

                var name = id != null && id.Equals(prop) ? "_id" : resolvePropertyName(prop.Name);

                // check if property has [BsonField] with a custom field name
                var field = (BsonFieldAttribute)prop.GetCustomAttributes(fieldAttr, false).FirstOrDefault();

                if (field != null)
                {
                    name = field.Name;
                }

                // check if property has [BsonId] to get with was setted AutoId = true
                var autoId = (BsonIdAttribute)prop.GetCustomAttributes(idAttr, false).FirstOrDefault();

                // checks if this proerty has [BsonIndex]
                var index = (BsonIndexAttribute)prop.GetCustomAttributes(indexAttr, false).FirstOrDefault();

                // if is _id field, do not accept index definition
                if (name == "_id")
                {
                    index = null;
                }

                // test if field name is OK (avoid to check in all instances) - do not test internal classes, like DbRef
                if (BsonDocument.IsValidFieldName(name) == false && isInternal == false)
                {
                    throw LiteException.InvalidFormat(prop.Name, name);
                }

                // create a property mapper
                var p = new PropertyMapper
                {
                    AutoId       = autoId == null ? true : autoId.AutoId,
                    FieldName    = name,
                    PropertyName = prop.Name,
                    PropertyType = prop.PropertyType,
                    IndexOptions = index == null ? null : index.Options,
                    Getter       = getter,
                    Setter       = setter
                };

                dict.Add(prop.Name, p);
            }

            return(dict);
        }
示例#5
0
        /// <summary>
        ///     Read all properties from a type - store in a static cache - exclude: Id and [BsonIgnore]
        /// </summary>
        public static Dictionary <string, PropertyMapper> GetProperties(Type type,
                                                                        Func <string, string> resolvePropertyName)
        {
            var dict  = new Dictionary <string, PropertyMapper>(StringComparer.OrdinalIgnoreCase);
            var id    = GetIdProperty(type);
            var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);

            foreach (var prop in props)
            {
                // ignore indexer property
                if (prop.GetIndexParameters().Length > 0)
                {
                    continue;
                }

                // ignore not read/write
                ////if (!prop.CanRead || !prop.CanWrite) continue;
                if (!prop.CanRead)
                {
                    continue;
                }

                var mapper =
                    (LiteMapperAttribute)prop.GetCustomAttributes(typeof(LiteMapperAttribute), false).FirstOrDefault() ??
                    new LiteMapperAttribute();

                // [BsonIgnore]
                if (mapper.Ignore)
                {
                    continue;
                }

                // check if property has [BsonField]
                var bsonField = prop.IsDefined(typeof(LiteMapperAttribute), false);

                // create getter/setter IL function
                var getter = CreateGetMethod(type, prop, bsonField);
                var setter = CreateSetMethod(type, prop, bsonField);

                // if not getter or setter - no mapping
                if (getter == null)
                {
                    continue;
                }

                var name = id != null && id.Equals(prop) ? "_id" : resolvePropertyName(prop.Name);

                // check if property has [BsonField] with a custom field name
                if (!string.IsNullOrEmpty(mapper.FieldName))
                {
                    name = mapper.FieldName;
                }

                // test if field name is OK (avoid to check in all instances) - do not test internal classes, like DbRef
                if (BsonDocument.IsValidFieldName(name) == false)
                {
                    throw LiteException.InvalidFormat(prop.Name, name);
                }

                // create a property mapper
                var p = new PropertyMapper
                {
                    AutoId       = mapper.AutoID != AutoID.False,
                    FieldName    = name,
                    PropertyName = prop.Name,
                    PropertyType = prop.PropertyType,
                    IndexOptions = name == "_id" || !bsonField ? null : mapper.Indexes,
                    Getter       = getter,
                    Setter       = setter
                };

                dict.Add(prop.Name, p);
            }

            return(dict);
        }