/// <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]); }
private YamlMapping DictionaryToMap(object obj) { var accessor = ObjectMemberAccessor.FindFor(obj.GetType()); var iter = ((IEnumerable)obj).GetEnumerator(); var dictionary = 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) ); } return(dictionary); }
private YamlMapping CreateMapping(string tag, object obj /*, bool by_content */) { var type = obj.GetType(); /* * if ( type.IsClass && !by_content && type.GetConstructor(Type.EmptyTypes) == null ) * throw new ArgumentException(string.Format("Type {0} has no default constructor.", type.FullName)); */ var mapping = map(); mapping.Tag = tag; AppendToAppeared(obj, mapping); // iterate props / fields var accessor = ObjectMemberAccessor.FindFor(type); foreach (var entry in accessor) { var name = entry.Key; var access = entry.Value; if (!access.ShouldSeriealize(obj)) { 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 ((access.SerializeMethod != YamlSerializeMethod.Content) || !(value is YamlMapping) || ((YamlMapping)value).Count > 0) { mapping.Add(MapKey(entry.Key), value); } } catch { } } } // if the object is IDictionary or IDictionary<,> if (accessor.IsDictionary && !accessor.IsReadOnly(obj)) { var dictionary = DictionaryToMap(obj); if (dictionary.Count > 0) { mapping.Add(MapKey("IDictionary.Entries"), dictionary); } } 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("ICollection.Items"), CreateSequence("!!seq", iter, accessor.ValueType)); } } } return(mapping); }
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: {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($"{type.FullName} is not a collection type."); } 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($"{type.FullName} is not a dictionary type."); } 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)) { throw new FormatException($"{type.FullName} does not have a member {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 {name} of {type.FullName} is not serializable."); } break; } } return(obj); }