Ejemplo n.º 1
0
        public static object ToFieldValue(this NSObject fieldValue, Type type)
        {
            if (fieldValue == null)
            {
                return(null);
            }

            switch (fieldValue)
            {
            case NSNumber number:
                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    type = type.GenericTypeArguments[0];
                }

                if (type == typeof(bool))
                {
                    return(number.BoolValue);
                }
                if (type == typeof(byte))
                {
                    return(number.ByteValue);
                }
                if (type == typeof(double))
                {
                    return(number.DoubleValue);
                }
                if (type == typeof(float))
                {
                    return(number.FloatValue);
                }
                if (type == typeof(int))
                {
                    return(number.Int32Value);
                }
                if (type == typeof(long))
                {
                    return(number.Int64Value);
                }
                if (type == typeof(sbyte))
                {
                    return(number.SByteValue);
                }
                if (type == typeof(short))
                {
                    return(number.Int16Value);
                }
                if (type == typeof(uint))
                {
                    return(number.UInt32Value);
                }
                if (type == typeof(ulong))
                {
                    return(number.UInt64Value);
                }
                if (type == typeof(ushort))
                {
                    return(number.UInt16Value);
                }
                return(Convert.ChangeType(number.DoubleValue, type));

            case NSString @string:
                return(@string.ToString());

            case Firebase.CloudFirestore.Timestamp timestamp:
            {
                var time = new Timestamp(timestamp);
                if (type == typeof(DateTime) || type == typeof(DateTime?))
                {
                    return(time.ToDateTime());
                }
                if (type == typeof(DateTimeOffset) || type == typeof(DateTimeOffset?))
                {
                    return(time.ToDateTimeOffset());
                }
                return(time);
            }

            case NSDate date:
            {
                var time = new Timestamp(date);
                if (type == typeof(DateTime) || type == typeof(DateTime?))
                {
                    return(time.ToDateTime());
                }
                if (type == typeof(DateTimeOffset) || type == typeof(DateTimeOffset?))
                {
                    return(time.ToDateTimeOffset());
                }
                return(time);
            }

            case NSArray array:
            {
                IList list;
                if (type.GetInterfaces().Contains(typeof(IList)))
                {
                    list = (IList)Activator.CreateInstance(type);
                }
                else if (type.IsGenericType)
                {
                    var listType = typeof(List <>).MakeGenericType(type.GenericTypeArguments[0]);
                    list = (IList)Activator.CreateInstance(listType);
                }
                else
                {
                    list = new List <object>();
                }

                var genericType = typeof(object);
                if (type.IsGenericType)
                {
                    genericType = type.GenericTypeArguments[0];
                }

                for (nuint i = 0; i < array.Count; i++)
                {
                    list.Add(array.GetItem <NSObject>(i).ToFieldValue(genericType));
                }
                return(list);
            }

            case NSDictionary dictionary:
            {
                object @object;
                if (type == typeof(object))
                {
                    @object = new Dictionary <string, object>();
                }
                else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary <,>))
                {
                    var dictionaryType = typeof(Dictionary <,>).MakeGenericType(type.GenericTypeArguments[0], type.GenericTypeArguments[1]);
                    @object = Activator.CreateInstance(dictionaryType);
                }
                else
                {
                    @object = Activator.CreateInstance(type);
                }

                if (@object is IDictionary dict)
                {
                    var genericType = typeof(object);
                    if (type.IsGenericType)
                    {
                        genericType = type.GenericTypeArguments[1];
                    }

                    foreach (var(key, value) in dictionary)
                    {
                        dict.Add(key.ToString(), value.ToFieldValue(genericType));
                    }
                }
                else
                {
                    var properties       = type.GetProperties();
                    var mappedProperties = properties.Select(p => (Property: p, Attribute: Attribute.GetCustomAttribute(p, typeof(MapToAttribute)) as MapToAttribute))
                                           .Where(t => t.Attribute != null)
                                           .ToDictionary(t => t.Attribute.Mapping, t => t.Property);
                    var igonoredProperties = properties.Where(p => Attribute.GetCustomAttribute(p, typeof(IgnoredAttribute)) != null);

                    foreach (var(key, value) in dictionary)
                    {
                        PropertyInfo property;
                        if (mappedProperties.ContainsKey(key.ToString()))
                        {
                            property = mappedProperties[key.ToString()];
                        }
                        else
                        {
                            property = type.GetProperty(key.ToString());
                        }

                        if (property != null && !igonoredProperties.Contains(property))
                        {
                            property.SetValue(@object, value.ToFieldValue(property.PropertyType));
                        }
                    }
                }
                return(@object);
            }

            case NSData data:
                if (type == typeof(byte[]))
                {
                    return(data.ToArray());
                }
                return(new MemoryStream(data.ToArray()));

            case Firebase.CloudFirestore.GeoPoint geoPoint:
                return(new GeoPoint(geoPoint));

            case Firebase.CloudFirestore.DocumentReference documentReference:
                return(new DocumentReferenceWrapper(documentReference));

            case NSNull @null:
                return(null);

            default:
                throw new ArgumentOutOfRangeException($"{fieldValue.GetType().FullName} is not supported");
            }
        }