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