コード例 #1
0
ファイル: CascadeSerializer.cs プロジェクト: Isuroku/Cascade
            public SCollect(object inInstance, Type type, IReflectionProvider provider)
            {
                _instance = inInstance;

                bool isHashSet = type.IsHashSet();

                if (isHashSet)
                {
                    _addToHashSet = provider.GetDelegate(type.GetMethod("Add"));
                    _list         = null;
                }
                else
                {
                    _addToHashSet = null;
                    _list         = inInstance as IList;
                }
            }
コード例 #2
0
        public object DeserializeInternal(SerializedObject serialized, Type declaredType, object existingInstance)
        {
            var type     = declaredType;
            var instance = existingInstance;

            // Atomic or null values
            if (serialized is SerializedAtom)
            {
                // The current value is replaced; they're immutable
                instance = (serialized as SerializedAtom).Value;
            }

            else if (serialized is SerializedXml)
            {
                var it = (serialized as SerializedXml);

                if (IsXmlType(declaredType))
                {
                    using (var sr = new StringReader((serialized as SerializedXml).Value))
                        using (var xr = XmlReader.Create(sr, new XmlReaderSettings {
                            ConformanceLevel = ConformanceLevel.Fragment
                        }))
                        {
                            instance = _reflectionProvider.Instantiate(declaredType);

                            var readXml = instance as IXmlSerializable;

                            if (readXml == null)
                            {
                                throw new Exception("DeserializeInternal error. readXml is null");
                            }

                            readXml.ReadXml(xr);
                        }
                }
                else if (IsSerializable(declaredType))
                {
                    using (var ms = new MemoryStream(Encoding.Default.GetBytes(it.Value)))
                    {
                        return(serializer.Deserialize(ms));
                    }
                }
            }

            // Dictionaries
            else if (type.IsGenericDictionary())
            {
                // Instantiate if necessary
                if (instance == null)
                {
                    instance = _reflectionProvider.Instantiate(type);
                }

                var dictionary = instance as IDictionary;

                if (dictionary == null)
                {
                    throw new Exception("DeserializeInternal  error. dictionary is null");
                }

                var genericArguments  = dictionary.GetType().GetGenericArguments();
                var keyDeclaredType   = genericArguments[0];
                var valueDeclaredType = genericArguments[1];

                var serializedAggregation = serialized as SerializedAggregate;

                if (serializedAggregation == null)
                {
                    throw new Exception("DeserializeInternal  error. serializedAggregation is null");
                }

                foreach (var key in serializedAggregation.Children.Keys)
                {
                    // Dictionaries always contain atoms as keys
                    SafeAddToDictionary(dictionary,
                                        DeserializeInternal(key as SerializedObject, keyDeclaredType, null),
                                        DeserializeInternal(serializedAggregation.Children[key], valueDeclaredType, null));
                }
            }

            // Arrays, lists and sets (any collection excluding dictionaries)
            else if (type.IsGenericCollection())
            {
                var isArray              = type.IsArray;
                var isHashSet            = type.IsHashSet();
                var serializedCollection = serialized as SerializedCollection;

                if (serializedCollection == null)
                {
                    throw new Exception("DeserializeInternal  error. serializedCollection is null");
                }

                var declaredItemType = type.IsArray ? type.GetElementType() : type.GetGenericArguments()[0];
                var genericListType  = typeof(System.Collections.Generic.List <>).MakeGenericType(declaredItemType);
                // Instantiate if necessary
                if (instance == null)
                {
                    if (isArray)
                    {
                        instance = Array.CreateInstance(declaredItemType, serializedCollection.Items.Count);
                    }
                    else if (type.IsAssignableFrom(genericListType))
                    {
                        instance = Activator.CreateInstance(genericListType);
                    }
                    else
                    {
                        if (declaredType.HasParameterlessConstructor())
                        {
                            instance = _reflectionProvider.Instantiate(declaredType) as IEnumerable;
                        }
                        else if (serializedCollection.Type.HasParameterlessConstructor())
                        {
                            instance = _reflectionProvider.Instantiate(serializedCollection.Type) as IEnumerable;
                        }
                    }
                }


                MethodHandler addToHashSet = null;
                if (isHashSet)
                {
                    addToHashSet = _reflectionProvider.GetDelegate(type.GetMethod("Add"));
                }

                var valueIndex = 0;
                foreach (var item in serializedCollection.Items)
                {
                    var value = DeserializeInternal(item, declaredItemType, null);

                    if (isArray)
                    {
                        var list = instance as IList;
                        if (list == null)
                        {
                            throw new Exception("DeserializeInternal collection error. list is null");
                        }
                        list[valueIndex++] = value;
                    }
                    else if (isHashSet)
                    {
                        // Potential problem if set already contains key...
                        addToHashSet(instance, value);
                    }
                    else if (instance is IList)
                    {
                        (instance as IList).Add(value);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
            }

            // Everything else (serialized with recursive property reflection)
            else
            {
                var mustInstantiate = instance == null;

                if (serialized.Type != null && declaredType != serialized.Type)
                {
                    type            = serialized.Type;
                    mustInstantiate = true;
                }

                if (mustInstantiate)
                {
                    instance = _reflectionProvider.Instantiate(type);
                }

                var serializedAggregation = serialized as SerializedAggregate;

                if (serializedAggregation == null)
                {
                    throw new Exception("DeserializeInternal collection error. serializedAggregation is null");
                }
                foreach (var memberInfo in _reflectionProvider.GetSerializableMembers(type))
                {
                    var memberAttr = _reflectionProvider.GetSingleAttributeOrDefault <SerializationAttribute>(memberInfo);
                    if (memberAttr.Ignore)
                    {
                        continue;
                    }

                    var memberType = memberInfo.GetMemberType();
                    var name       = memberAttr.Name ?? memberInfo.Name;

                    // Checking if it's a class before doing GetValue doesn't speed up the process
                    var valueFound = serializedAggregation.Children.ContainsKey(name);

                    if (!valueFound)
                    {
                        if (memberAttr.Required)
                        {
                            throw new InvalidOperationException(string.Format("MissingRequiredValue {0} {1}", name, type.Name));
                        }
                    }
                    else
                    {
                        try
                        {
                            var currentValue = _reflectionProvider.GetValue(memberInfo, instance);
                            var readValue    = DeserializeInternal(serializedAggregation[name], memberType, currentValue);
                            // This dirty check is naive and doesn't provide performance benefits
                            //if (memberType.IsClass && readValue != currentValue && (readValue == null || !readValue.Equals(currentValue)))
                            _reflectionProvider.SetValue(memberInfo, instance, readValue);
                        }
                        catch
                        {
                        }
                    }
                }
            }

            return(instance);
        }