YamlNode ObjectToNodeSub(object obj, Type expect) { // !!null if (obj == null) { return(str("!!null", "null")); } YamlScalar node; if (config.TagResolver.Encode(obj, out node)) { return(node); } var type = obj.GetType(); if (obj is IntPtr || type.IsPointer) { throw new ArgumentException("Pointer object '{0}' can not be serialized.".DoFormat(obj.ToString())); } if (obj is char) { // config.TypeConverter.ConvertToString("\0") does not show "\0" var n = str(TypeNameToYamlTag(type), obj.ToString()); return(n); } // bool, byte, sbyte, decimal, double, float, int ,uint, long, ulong, short, ushort, string, enum if (type.IsPrimitive || type.IsEnum || type == typeof(decimal) || type == typeof(string)) { var n = str(TypeNameToYamlTag(type), config.TypeConverter.ConvertToString(obj)); return(n); } // TypeConverterAttribute if (EasyTypeConverter.IsTypeConverterSpecified(type)) { return(str(TypeNameToYamlTag(type), config.TypeConverter.ConvertToString(obj))); } // array if (type.IsArray) { return(CreateArrayNode((Array)obj)); } if (type == typeof(Dictionary <object, object>)) { return(DictionaryToMap(obj)); } // class / struct if (type.IsClass || type.IsValueType) { return(CreateMapping(TypeNameToYamlTag(type), obj)); } throw new NotImplementedException( "Type '{0}' could not be written".DoFormat(type.FullName) ); }
object ScalarToObject(YamlScalar node, Type type) { if (type == null) { throw new FormatException("Could not find a type '{0}'.".DoFormat(node.Tag)); } // To accommodate the !!int and !!float encoding, all "_"s in integer and floating point values // are simply neglected. if (type == typeof(byte) || type == typeof(sbyte) || type == typeof(short) || type == typeof(ushort) || type == typeof(int) || type == typeof(uint) || type == typeof(long) || type == typeof(ulong) || type == typeof(float) || type == typeof(decimal)) { return(config.TypeConverter.ConvertFromString(node.Value.Replace("_", ""), type)); } // 変換結果が見かけ上他の型に見える可能性がある場合を優先的に変換 // 予想通りの型が見つからなければエラーになる条件でもある if (type.IsEnum || type.IsPrimitive || type == typeof(char) || type == typeof(bool) || type == typeof(string) || EasyTypeConverter.IsTypeConverterSpecified(type)) { return(config.TypeConverter.ConvertFromString(node.Value, type)); } if (type.IsArray) { // Split dimension from base64 strings var s = node.Value; var regex = new Regex(@" *\[([0-9 ,]+)\][\r\n]+((.+|[\r\n])+)"); int[] dimension; byte[] binary; var elementSize = Marshal.SizeOf(type.GetElementType()); if (type.GetArrayRank() == 1) { binary = Convert.FromBase64CharArray(s.ToCharArray(), 0, s.Length); var arrayLength = binary.Length / elementSize; dimension = new int[] { arrayLength }; } else { var m = regex.Match(s); if (!m.Success) { throw new FormatException("Irregal binary array"); } // Create array from dimension dimension = m.Groups[1].Value.Split(',').Select(n => Convert.ToInt32(n)).ToArray(); if (type.GetArrayRank() != dimension.Length) { throw new FormatException("Irregal binary array"); } // Fill values s = m.Groups[2].Value; binary = Convert.FromBase64CharArray(s.ToCharArray(), 0, s.Length); } var paramType = dimension.Select(n => typeof(int) /* n.GetType() */).ToArray(); var array = (Array)type.GetConstructor(paramType).Invoke(dimension.Cast <object>().ToArray()); if (binary.Length != array.Length * elementSize) { throw new FormatException("Irregal binary: data size does not match to array dimension"); } int j = 0; for (int i = 0; i < array.Length; i++) { var p = Marshal.UnsafeAddrOfPinnedArrayElement(array, i); Marshal.Copy(binary, j, p, elementSize); j += elementSize; } return(array); } if (node.Value == "") { return(config.Activator.Activate(type)); } else { return(TypeDescriptor.GetConverter(type).ConvertFromString(node.Value)); } }