コード例 #1
0
ファイル: CascadeSerializer.cs プロジェクト: Isuroku/Cascade
        object DeserializeClass(object inInstance, IKey inKey, Type type, int inStructDeep, ILogPrinter inLogger)
        {
            IKey type_key = inKey.GetChild("RealObjectType");

            if (type_key != null)
            {
                string type_name     = type_key.GetValueAsString(0);
                string assembly_name = type_key.GetValueAsString(1);

                try
                {
                    Assembly assembly = Assembly.Load(assembly_name);
                    Type     obj_type = assembly.GetType(type_name, true);
                    if (obj_type != null)
                    {
                        type = obj_type;
                    }
                }
                catch (Exception ex)
                {
                    LogError(inLogger, string.Format("Cant take type from RealObjectType {0}. Exception: {1}", type_name, ex.Message));
                }
            }

            object instance = inInstance;

            if (instance == null)
            {
                instance = _reflectionProvider.Instantiate(type, inLogger);
            }

            if (instance != null)
            {
                //MethodInfo mi = type.GetMethod("DeserializationFromCscd", new Type[] { typeof(CascadeParser.IKey), typeof(CascadeParser.ILogPrinter) });
                MethodInfo mi = type.GetMethod("DeserializationFromCscd", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                if (mi != null)
                {
                    if (inKey != null && !inKey.IsEmpty)
                    {
                        IKey key = inKey;
                        mi.Invoke(instance, new object[] { key, inLogger });
                    }
                }
                else
                {
                    MemberInfo[] member_infos = _reflectionProvider.GetSerializableMembers(type);
                    foreach (MemberInfo memberInfo in member_infos)
                    {
                        SCustomMemberParams member_params = GetMemberParams(memberInfo);

                        Type memberType = memberInfo.GetMemberType();

                        IKey sub_key = inKey.GetChild(member_params.ChangedName);
                        if (sub_key == null)
                        {
                            sub_key = inKey.GetChild(member_params.Name);
                        }

                        if (sub_key != null)
                        {
                            object readValue;
                            if (member_params.Converter != null)
                            {
                                readValue = member_params.Converter.ReadKey(sub_key, inLogger);
                            }
                            else
                            {
                                readValue = DeserializeInternal(null, sub_key, memberType, 0, inStructDeep + 1, inLogger);
                            }

                            // 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, inLogger);
                        }
                        else if (member_params.DefaultValue != null)
                        {
                            _reflectionProvider.SetValue(memberInfo, instance, member_params.DefaultValue, inLogger);
                        }
                        else if (memberType.IsClass || memberType.IsStruct())
                        {
                            object already_exists_member = _reflectionProvider.GetValue(memberInfo, instance);
                            if (already_exists_member != null)
                            {
                                //for set default values inside this object
                                already_exists_member = DeserializeInternal(already_exists_member, IKeyFactory.CreateKey(string.Empty), memberType, 0, inStructDeep + 1, inLogger);
                                if (already_exists_member != null)
                                {
                                    _reflectionProvider.SetValue(memberInfo, instance, already_exists_member, inLogger);
                                }
                            }
                        }
                    }
                }

                mi = type.GetMethod("OnDeserializedMethod", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                if (mi != null)
                {
                    var context = new StreamingContext(StreamingContextStates.Other);
                    mi.Invoke(instance, new object[] { context });
                }
            }

            return(instance);
        }
コード例 #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);
        }