object MappingToObject(YamlMapping map, Type type, object obj, Dictionary<YamlNode, object> appeared)
        {
            // 1) Give a chance to deserialize through a IYamlSerializable interface
            var serializable = config.Serializable.FindSerializable(context, obj, type);
            if (serializable != null)
            {
                return serializable.Deserialize(context, map, type);
            }
            
            // 2) Naked !!map is constructed as Dictionary<object, object>.
            if ( ( ( map.ShorthandTag() == "!!map" && type == null ) || type == typeof(Dictionary<object,object>) ) && obj == null ) {
                var objectDictionary = new Dictionary<object, object>();
                appeared.Add(map, objectDictionary);
                foreach ( var entry in map ) 
                    objectDictionary.Add(NodeToObjectInternal(entry.Key, null, appeared), NodeToObjectInternal(entry.Value, null, appeared));
                return objectDictionary;
            }

            if (type == null)
            {
                throw new FormatException("Unable to find type for {0}]".DoFormat(map.ToString()));
            }

            // 3) Give a chance to config.Activator
            if ( obj == null ) 
            {
                obj = config.Activator.Activate(type);
                appeared.Add(map, obj);
            } else {
                if ( appeared.ContainsKey(map) )
                    throw new InvalidOperationException("This member is not writeable: {0}".DoFormat(obj.ToString()));
            }

            var dictionary = obj as IDictionary;
            var access = ObjectMemberAccessor.FindFor(type);
            foreach (var entry in map)
            {
                if (obj == null)
                    throw new InvalidOperationException("Object is not initialized");

                // If this is a pure dictionary, we can directly add key,value to it
                if (dictionary != null && access.IsPureDictionary)
                {
                    dictionary.Add(NodeToObjectInternal(entry.Key, access.KeyType, appeared), NodeToObjectInternal(entry.Value, access.ValueType, appeared));
                    continue;
                }

                // Else go the long way
                var name = (string)NodeToObjectInternal(entry.Key, typeof(string), appeared);

                if (name == "~Items")
                {
                    if (entry.Value is YamlSequence)
                    {
                        SequenceToObject((YamlSequence)entry.Value, obj.GetType(), obj, appeared);
                    }
                    else if (entry.Value is YamlMapping)
                    {
                        if (!access.IsDictionary || dictionary == null)
                            throw new FormatException("{0} is not a dictionary type.".DoFormat(type.FullName));
                        dictionary.Clear();
                        foreach (var child in (YamlMapping)entry.Value)
                            dictionary.Add(NodeToObjectInternal(child.Key, access.KeyType, appeared), NodeToObjectInternal(child.Value, access.ValueType, appeared));
                    }
                    else
                    {
                        throw new InvalidOperationException("Member {0} of {1} is not serializable.".DoFormat(name, type.FullName));
                    }
                }
                else
                {
                    if (!access.ContainsKey(name))
                        throw new FormatException("{0} does not have a member {1}.".DoFormat(type.FullName, name));
                    switch (access[name].SerializeMethod)
                    {
                        case YamlSerializeMethod.Assign:
                            access[obj, name] = NodeToObjectInternal(entry.Value, access[name].Type, appeared);
                            break;
                        case YamlSerializeMethod.Content:
                            MappingToObject((YamlMapping)entry.Value, access[name].Type, access[obj, name], appeared);
                            break;
                        case YamlSerializeMethod.Binary:
                            access[obj, name] = ScalarToObject((YamlScalar)entry.Value, access[name].Type);
                            break;
                        default:
                            throw new InvalidOperationException(
                                "Member {0} of {1} is not serializable.".DoFormat(name, type.FullName));
                    }
                }
            }
            return obj;
        }
示例#2
0
        object MappingToObject(YamlMapping map, Type type, object obj, Dictionary <YamlNode, object> appeared)
        {
            // Naked !!map is constructed as Dictionary<object, object>.
            if (((map.ShorthandTag() == "!!map" && type == null) || type == typeof(Dictionary <object, object>)) && obj == null)
            {
                var dict = new Dictionary <object, object>();
                appeared.Add(map, dict);
                foreach (var entry in map)
                {
                    dict.Add(NodeToObjectInternal(entry.Key, null, appeared), NodeToObjectInternal(entry.Value, null, appeared));
                }
                return(dict);
            }

            if (obj == null)
            {
                obj = config.Activator.Activate(type);
                appeared.Add(map, obj);
            }
            else
            {
                if (appeared.ContainsKey(map))
                {
                    throw new InvalidOperationException("This member is not writeable: {0}".DoFormat(obj.ToString()));
                }
            }

            var access = ObjectMemberAccessor.FindFor(type);

            foreach (var entry in map)
            {
                if (obj == null)
                {
                    throw new InvalidOperationException("Object is not initialized");
                }
                var name = (string)NodeToObjectInternal(entry.Key, typeof(string), appeared);
                switch (name)
                {
                case "ICollection.Items":
                    if (access.CollectionAdd == null)
                    {
                        throw new FormatException("{0} is not a collection type.".DoFormat(type.FullName));
                    }
                    access.CollectionClear(obj);
                    foreach (var item in (YamlSequence)entry.Value)
                    {
                        access.CollectionAdd(obj, NodeToObjectInternal(item, access.ValueType, appeared));
                    }
                    break;

                case "IDictionary.Entries":
                    if (!access.IsDictionary)
                    {
                        throw new FormatException("{0} is not a dictionary type.".DoFormat(type.FullName));
                    }
                    var dict = obj as IDictionary;
                    dict.Clear();
                    foreach (var child in (YamlMapping)entry.Value)
                    {
                        dict.Add(NodeToObjectInternal(child.Key, access.KeyType, appeared), NodeToObjectInternal(child.Value, access.ValueType, appeared));
                    }
                    break;

                default:
                    if (!access.ContainsKey(name))
                    {
                        // ignoring non existing properties
                        //throw new FormatException("{0} does not have a member {1}.".DoFormat(type.FullName, name));
                        continue;
                    }
                    switch (access[name].SerializeMethod)
                    {
                    case YamlSerializeMethod.Assign:
                        access[obj, name] = NodeToObjectInternal(entry.Value, access[name].Type, appeared);
                        break;

                    case YamlSerializeMethod.Content:
                        MappingToObject((YamlMapping)entry.Value, access[name].Type, access[obj, name], appeared);
                        break;

                    case YamlSerializeMethod.Binary:
                        access[obj, name] = ScalarToObject((YamlScalar)entry.Value, access[name].Type);
                        break;

                    default:
                        throw new InvalidOperationException(
                                  "Member {0} of {1} is not serializable.".DoFormat(name, type.FullName));
                    }
                    break;
                }
            }
            return(obj);
        }
        object MappingToObject(YamlMapping map, Type type, object obj, Dictionary <YamlNode, object> appeared)
        {
            // 1) Give a chance to deserialize through a IYamlSerializable interface
            var serializable = config.Serializable.FindSerializable(context, obj, type);

            if (serializable != null)
            {
                return(serializable.Deserialize(context, map, type));
            }

            // 2) Naked !!map is constructed as Dictionary<object, object>.
            if (((map.ShorthandTag() == "!!map" && type == null) || type == typeof(Dictionary <object, object>)) && obj == null)
            {
                var objectDictionary = new Dictionary <object, object>();
                appeared.Add(map, objectDictionary);
                foreach (var entry in map)
                {
                    objectDictionary.Add(NodeToObjectInternal(entry.Key, null, appeared), NodeToObjectInternal(entry.Value, null, appeared));
                }
                return(objectDictionary);
            }

            if (type == null)
            {
                throw new FormatException("Unable to find type for {0}]".DoFormat(map.ToString()));
            }

            // 3) Give a chance to config.Activator
            if (obj == null)
            {
                obj = config.Activator.Activate(type);
                appeared.Add(map, obj);
            }
            else
            {
                if (appeared.ContainsKey(map))
                {
                    throw new InvalidOperationException("This member is not writeable: {0}".DoFormat(obj.ToString()));
                }
            }

            var dictionary = obj as IDictionary;
            var access     = ObjectMemberAccessor.FindFor(type);

            foreach (var entry in map)
            {
                if (obj == null)
                {
                    throw new InvalidOperationException("Object is not initialized");
                }

                // If this is a pure dictionary, we can directly add key,value to it
                if (dictionary != null && access.IsPureDictionary)
                {
                    dictionary.Add(NodeToObjectInternal(entry.Key, access.KeyType, appeared), NodeToObjectInternal(entry.Value, access.ValueType, appeared));
                    continue;
                }

                // Else go the long way
                var name = (string)NodeToObjectInternal(entry.Key, typeof(string), appeared);

                if (name == "~Items")
                {
                    if (entry.Value is YamlSequence)
                    {
                        SequenceToObject((YamlSequence)entry.Value, obj.GetType(), obj, appeared);
                    }
                    else if (entry.Value is YamlMapping)
                    {
                        if (!access.IsDictionary || dictionary == null)
                        {
                            throw new FormatException("{0} is not a dictionary type.".DoFormat(type.FullName));
                        }
                        dictionary.Clear();
                        foreach (var child in (YamlMapping)entry.Value)
                        {
                            dictionary.Add(NodeToObjectInternal(child.Key, access.KeyType, appeared), NodeToObjectInternal(child.Value, access.ValueType, appeared));
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("Member {0} of {1} is not serializable.".DoFormat(name, type.FullName));
                    }
                }
                else
                {
                    if (!access.ContainsKey(name))
                    {
                        throw new FormatException("{0} does not have a member {1}.".DoFormat(type.FullName, name));
                    }
                    switch (access[name].SerializeMethod)
                    {
                    case YamlSerializeMethod.Assign:
                        access[obj, name] = NodeToObjectInternal(entry.Value, access[name].Type, appeared);
                        break;

                    case YamlSerializeMethod.Content:
                        MappingToObject((YamlMapping)entry.Value, access[name].Type, access[obj, name], appeared);
                        break;

                    case YamlSerializeMethod.Binary:
                        access[obj, name] = ScalarToObject((YamlScalar)entry.Value, access[name].Type);
                        break;

                    default:
                        throw new InvalidOperationException(
                                  "Member {0} of {1} is not serializable.".DoFormat(name, type.FullName));
                    }
                }
            }
            return(obj);
        }