Exemplo n.º 1
0
        private void DictionaryToMap(object obj, YamlMapping mapping)
        {
            var accessor = ObjectMemberAccessor.FindFor(obj.GetType());
            var iter     = ((IEnumerable)obj).GetEnumerator();

            // When this is a pure dictionary, we can directly add key,value to YamlMapping
            var dictionary = accessor.IsPureDictionary ? mapping : map();
            Func <object, object> key = null, value = null;

            while (iter.MoveNext())
            {
                if (key == null)
                {
                    var keyvalue  = iter.Current.GetType();
                    var keyprop   = keyvalue.GetProperty("Key");
                    var valueprop = keyvalue.GetProperty("Value");
                    key   = o => keyprop.GetValue(o, new object[0]);
                    value = o => valueprop.GetValue(o, new object[0]);
                }
                dictionary.Add(
                    ObjectToNode(key(iter.Current), accessor.KeyType),
                    ObjectToNode(value(iter.Current), accessor.ValueType)
                    );
            }

            if (!accessor.IsPureDictionary && dictionary.Count > 0)
            {
                mapping.Add(MapKey("~Items"), dictionary);
            }
        }
Exemplo n.º 2
0
 /// <summary>
 ///
 /// 指定した型へのアクセス方法を表すインスタンスを返す
 /// キャッシュに存在すればそれを返す
 /// キャッシュに存在しなければ新しく作って返す
 /// 作った物はキャッシュされる
 /// </summary>
 /// <param name="type">クラスまたは構造体を表す型情報</param>
 /// <returns></returns>
 public static ObjectMemberAccessor FindFor(Type type)
 {
     if (!MemberAccessors.ContainsKey(type))
     {
         MemberAccessors[type] = new ObjectMemberAccessor(type);
     }
     return(MemberAccessors[type]);
 }
 /// <summary>
 /// 
 /// 指定した型へのアクセス方法を表すインスタンスを返す
 /// キャッシュに存在すればそれを返す
 /// キャッシュに存在しなければ新しく作って返す
 /// 作った物はキャッシュされる
 /// </summary>
 /// <param name="type">クラスまたは構造体を表す型情報</param>
 /// <returns></returns>
 public static ObjectMemberAccessor FindFor(Type type)
 {
     if ( !MemberAccessors.ContainsKey(type) )
         MemberAccessors[type] = new ObjectMemberAccessor(type);
     return MemberAccessors[type];
 }
Exemplo n.º 4
0
        private YamlNode CreateMappingOrSequence(string tag, object obj /*, bool by_content */)
        {
            var type     = obj.GetType();
            var accessor = ObjectMemberAccessor.FindFor(type);


            // In the case of a pure list, we are creating directly a sequence
            if (accessor.IsPureList)
            {
                // if the object is ICollection<> or IList

                var isReadOnly = accessor.IsReadOnly(obj);
                if (accessor.CollectionAdd != null && !isReadOnly)
                {
                    var iter = ((IEnumerable)obj).GetEnumerator();
                    if (iter.MoveNext())
                    { // Count > 0
                        iter.Reset();
                        return(CreateSequence("!!seq", iter, accessor.ValueType));
                    }
                }
                return(null);
            }

            /*
             * if ( type.IsClass && !by_content && type.GetConstructor(Type.EmptyTypes) == null )
             *  throw new ArgumentException("Type {0} has no default constructor.".DoFormat(type.FullName));
             */

            var mapping = map();

            mapping.Tag = tag;
            AppendToAppeared(obj, mapping);

            var isList = obj is IList;

            // iterate props / fields
            foreach (var entry in accessor)
            {
                var name   = entry.Key;
                var access = entry.Value;
                if (!access.ShouldSeriealize(obj) || (isList && name == "Capacity" && !config.EmitCapacityForList))
                {
                    continue;
                }
                if (access.SerializeMethod == YamlSerializeMethod.Binary)
                {
                    var array = CreateBinaryArrayNode((Array)access.Get(obj));
                    AppendToAppeared(access.Get(obj), array);
                    array.Properties["expectedTag"] = TypeNameToYamlTag(access.Type);
                    mapping.Add(MapKey(entry.Key), array);
                }
                else
                {
                    try {
                        var value = ObjectToNode(access.Get(obj), access.Type);
                        if (value != null && (access.SerializeMethod != YamlSerializeMethod.Content ||
                                              !(value is YamlMapping) || ((YamlMapping)value).Count > 0))
                        {
                            mapping.Add(MapKey(entry.Key), value);
                        }
                    }
                    catch (Exception ex)
                    {
                        // TODO log this exception
                    }
                }
            }
            // if the object is IDictionary or IDictionary<,>
            if (accessor.IsDictionary && !accessor.IsReadOnly(obj))
            {
                DictionaryToMap(obj, mapping);
            }
            else
            {
                // if the object is ICollection<> or IList
                if (accessor.CollectionAdd != null && !accessor.IsReadOnly(obj))
                {
                    var iter = ((IEnumerable)obj).GetEnumerator();
                    if (iter.MoveNext())     // Count > 0
                    {
                        iter.Reset();
                        mapping.Add(MapKey("~Items"), CreateSequence("!!seq", iter, accessor.ValueType));
                    }
                }
            }
            return(mapping);
        }
Exemplo n.º 5
0
        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);
        }
Exemplo n.º 6
0
        object SequenceToObject(YamlSequence seq, Type type, object obj, Dictionary <YamlNode, object> appeared)
        {
            if (type == null)
            {
                type = typeof(object[]);
            }

            // 1) Give a chance to deserialize through a IYamlSerializable interface
            var serializable = config.Serializable.FindSerializable(context, null, type);

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

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

            if (type.IsArray)
            {
                var lengthes = new int[type.GetArrayRank()];
                GetLengthes(seq, 0, lengthes);
                var array = (Array)type.GetConstructor(lengthes.Select(l => typeof(int) /* l.GetType() */).ToArray())
                            .Invoke(lengthes.Cast <object>().ToArray());
                appeared.Add(seq, array);
                var indices = new int[type.GetArrayRank()];
                SetArrayElements(array, seq, 0, indices, type.GetElementType(), appeared);
                return(array);
            }


            var collection = obj as ICollection;

            if (collection != null)
            {
                var access = ObjectMemberAccessor.FindFor(type);

                // If this is a pure list
                if (access.CollectionAdd == null)
                {
                    throw new FormatException("{0} is not a collection type.".DoFormat(type.FullName));
                }
                access.CollectionClear(obj);
                foreach (var item in seq)
                {
                    access.CollectionAdd(obj, NodeToObjectInternal(item, access.ValueType, appeared));
                }

                return(obj);
            }

            // TODO Add support for lists
            throw new FormatException("Unsupported type [{0}] for sequence [{1}]".DoFormat(type.Name, seq));
        }