Exemple #1
0
        /// <summary>
        /// Try find a Type Resolver for declaring type
        /// </summary>
        private bool TryGetResolver(Type declaringType, out ITypeResolver typeResolver)
        {
            // get method declaring type - if is from any kind of list, read as Enumerable
            var isList     = Reflection.IsList(declaringType);
            var isNullable = Reflection.IsNullable(declaringType);

            var type =
                isList ? typeof(Enumerable) :
                isNullable ? typeof(Nullable) :
                declaringType;

            return(_resolver.TryGetValue(type, out typeResolver));
        }
        /// <summary>
        /// Deserilize a BsonValue to .NET object based on type parameter
        /// </summary>
        public object Deserialize(Type type, BsonValue value)
        {
            // null value - null returns
            if (value.IsNull)
            {
                return(null);
            }

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

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

            var typeInfo = type.GetTypeInfo();

            // check if your type is already a BsonValue/BsonDocument/BsonArray
            if (type == typeof(BsonValue))
            {
                return(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));
            }

            // special cast to UInt64 to Int64
            else if (type == typeof(UInt64))
            {
                return(unchecked ((UInt64)value.AsInt64));
            }

            // enum value is an int
            else if (typeInfo.IsEnum)
            {
                if (value.IsString)
                {
                    return(Enum.Parse(type, value.AsString));
                }

                if (value.IsNumber)
                {
                    return(value.AsInt32);
                }
            }

            // if value is array, deserialize as array
            else if (value.IsArray)
            {
                // when array are from an object (like in Dictionary<string, object> { ["array"] = new string[] { "a", "b" }
                if (type == typeof(object))
                {
                    return(this.DeserializeArray(typeof(object), value.AsArray));
                }
                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)
            {
                // if type is anonymous use special handler
                if (type.IsAnonymousType())
                {
                    return(this.DeserializeAnonymousType(type, value.AsDocument));
                }

                var doc = value.AsDocument;

                // test if value is object and has _type
                if (doc.TryGetValue("_type", out var typeField) && typeField.IsString)
                {
                    type = _typeNameBinder.GetType(typeField.AsString);

                    if (type == null)
                    {
                        throw LiteException.InvalidTypedName(typeField.AsString);
                    }
                }
                // when complex type has no definition (== typeof(object)) use Dictionary<string, object> to better set values
                else if (type == typeof(object))
                {
                    type = typeof(Dictionary <string, object>);
                }

                var entity = this.GetEntityMapper(type);

                // initialize CreateInstance
                if (entity.CreateInstance == null)
                {
                    entity.CreateInstance =
                        this.GetTypeCtor(entity) ??
                        ((BsonDocument v) => Reflection.CreateInstance(entity.ForType));
                }

                var o = _typeInstantiator(type) ?? entity.CreateInstance(doc);

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

                        this.DeserializeDictionary(k, t, dict, value.AsDocument);
                    }
                    else
                    {
                        this.DeserializeDictionary(typeof(object), typeof(object), dict, value.AsDocument);
                    }
                }
                else
                {
                    this.DeserializeObject(entity, 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);
        }
Exemple #3
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.GetTypeInfo().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);

                    if (type == null)
                    {
                        throw LiteException.InvalidTypedName(typeField.AsString);
                    }
                }

                var o = Reflection.CreateInstance(type);

                if (o is IDictionary && type.GetTypeInfo().IsGenericType)
                {
#if !NETFULL
                    var k = type.GetTypeInfo().GenericTypeArguments[0];
                    var t = type.GetTypeInfo().GenericTypeArguments[1];
#else
                    var k = type.GetGenericArguments()[0];
                    var t = type.GetGenericArguments()[1];
#endif

                    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);
        }
        private object Deserialize(Type type, BsonValue value)
        {
            if (value.IsNull)
            {
                return(null);
            }

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

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

            // bson types convert
            else if (_bsonTypes.Contains(type))
            {
                return(value.RawValue);
            }
            else if (_basicTypes.Contains(type))
            {
                return(Convert.ChangeType(value.RawValue, type));
            }
            else if (type.IsEnum)
            {
                return(Enum.Parse(type, value.AsString));
            }
            else if (type.IsArray)
            {
                return(this.DeserializeArray(type.GetElementType(), value.AsArray));
            }

            // test if has a custom type implementation
            Func <BsonValue, object> custom;

            if (_customDeserializer.TryGetValue(type, out custom))
            {
                return(custom(value));
            }

            // create instance for object type
            var o = Reflection.CreateInstance(type);

            // check if type is a IList
            if (o is IList && type.IsGenericType)
            {
                this.DeserializeList(Reflection.UnderlyingTypeOf(type), (IList)o, value.AsArray);
            }
            else 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
            {
                // otherwise is plain object
                this.DeserializeObject(type, o, value.AsDocument);
            }

            return(o);
        }
        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));
            }

            // special cast to UInt64 to Int64
            else if (type == typeof(UInt64))
            {
                return(unchecked ((UInt64)((Int64)value.RawValue)));
            }

            // enum value is an int
            else if (type.GetTypeInfo().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)
            {
                // when array are from an object (like in Dictionary<string, object> { ["array"] = new string[] { "a", "b" }
                if (type == typeof(object))
                {
                    return(this.DeserializeArray(typeof(object), value.AsArray));
                }
                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))
                {
                    string storedType = typeField.AsString;
                    string resultType = null;
                    if (TypeMapper.TryGetValue(storedType, out resultType))
                    {
                        storedType = resultType;
                    }
                    typeField = storedType + sAssemblyName;
                    type      = Type.GetType(typeField.AsString);

                    if (type == null)
                    {
                        throw LiteException.InvalidTypedName(typeField.AsString);
                    }
                }
                // when complex type has no definition (== typeof(object)) use Dictionary<string, object> to better set values
                else if (type == typeof(object))
                {
                    type = typeof(Dictionary <string, object>);
                }

                var o = _typeInstantiator(type);

                if (o is IDictionary && type.GetTypeInfo().IsGenericType)
                {
#if NET35
                    var k = type.GetGenericArguments()[0];
                    var t = type.GetGenericArguments()[1];
#else
                    var k = type.GetTypeInfo().GenericTypeArguments[0];
                    var t = type.GetTypeInfo().GenericTypeArguments[1];
#endif

                    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);
        }