Esempio n. 1
0
        // ---- Serialization ----

        private void CollectArrayContents(object obj)
        {
            // Put strings into the string array.
            if (obj is string)
            {
                _stringArray.Add((string)obj);
                return;
            }

            // Put paths into the path array (if supported).
            if (Settings.SupportPaths)
            {
                if (obj is List <ByamlPathPoint> )
                {
                    _pathArray.Add((List <ByamlPathPoint>)obj);
                    return;
                }
            }

            // Traverse through arrays if the element type is of interest.
            if (obj is IList)
            {
                IList objArray    = (IList)obj;
                Type  elementType = objArray.GetType().GetTypeInfo().GetElementType();
                if (elementType == typeof(string) || elementType is IList || IsTypeByamlObject(elementType))
                {
                    foreach (object element in objArray)
                    {
                        CollectArrayContents(element);
                    }
                }
                return;
            }

            // Traverse through other types decorated with the ByamlObjectAttribute and collect their keys and values.
            Type type = obj.GetType();

            if (IsTypeByamlObject(type))
            {
                ByamlObjectInfo objectInfo;
                if (!_byamlObjectInfos.TryGetValue(type, out objectInfo))
                {
                    objectInfo = new ByamlObjectInfo(type);
                    _byamlObjectInfos.Add(type, objectInfo);
                }
                // Query the custom values and remember them for when to actually store them in the BYAML.
                if (objectInfo.ImplementsByamlSerializable)
                {
                    IByamlSerializable          byamlSerializable = (IByamlSerializable)obj;
                    Dictionary <string, object> customMembers     = new Dictionary <string, object>();
                    byamlSerializable.SerializeByaml(customMembers);
                    foreach (KeyValuePair <string, object> customMember in customMembers)
                    {
                        _nameArray.Add(customMember.Key);
                        CollectArrayContents(customMember.Value);
                    }
                    if (customMembers.Count > 0)
                    {
                        _customMembers.Add(obj, customMembers);
                    }
                }
                // Go through the default members.
                foreach (KeyValuePair <string, ByamlMemberInfo> member in objectInfo.Members)
                {
                    object value = member.Value.GetValue(obj);
                    if (value != null || !member.Value.Optional)
                    {
                        _nameArray.Add(member.Key);
                        if (value != null)
                        {
                            CollectArrayContents(value);
                        }
                    }
                }
                return;
            }
        }
Esempio n. 2
0
        private object ReadDictionary(BinaryDataReader reader, Type type, int length)
        {
            // Get the information required to serialize this type (for Nullables take the underlying type).
            Type nullableType = Nullable.GetUnderlyingType(type);

            if (nullableType != null)
            {
                type = nullableType;
            }
            ByamlObjectInfo objectInfo;

            if (!_byamlObjectInfos.TryGetValue(type, out objectInfo))
            {
                objectInfo = new ByamlObjectInfo(type);
                _byamlObjectInfos.Add(type, objectInfo);
            }

            // Instantiate the type and read in the elements. Use a given instance as the root if available.
            object instance;

            if (_instance == null)
            {
                instance = Activator.CreateInstance(type, true);
            }
            else
            {
                instance  = _instance;
                _instance = null;
            }
            // Collect them in a dictionary for custom deserialization.
            Dictionary <string, object> dictionary = new Dictionary <string, object>();

            for (int i = 0; i < length; i++)
            {
                uint          indexAndType  = reader.ReadUInt32();
                int           nodeNameIndex = (int)Get3MsbBytes(indexAndType);
                ByamlNodeType nodeType      = (ByamlNodeType)Get1MsbByte(indexAndType);
                string        key           = _nameArray[nodeNameIndex];
                // Find a member for it to map the value to.
                object          value;
                ByamlMemberInfo member;
                if (objectInfo.Members.TryGetValue(key, out member))
                {
                    // The key could be mapped to a member, read it as the member's type.
                    value = ReadValue(reader, member.Type, nodeType);
                    member.SetValue(instance, value);
                }
                else
                {
                    // If the key could not be mapped to a member, add it to the dictionary for custom deserialization.
                    //Debug.WriteLine($"No member in {type.Name} found to map key \"{key}\" to.");
                    value = ReadValue(reader, nodeType.GetInstanceType(), nodeType);
                }
                dictionary.Add(key, value);
            }

            // Call IByamlSerializable methods if the interface was implemented.
            if (objectInfo.ImplementsByamlSerializable)
            {
                IByamlSerializable byamlSerializable = (IByamlSerializable)instance;
                byamlSerializable.DeserializeByaml(dictionary);
            }

            // Check if any required fields were not filled.
            foreach (ByamlMemberInfo member in objectInfo.Members.Values)
            {
                if (!member.Optional && member.GetValue(instance) == null)
                {
                    throw new ByamlException(
                              $"Member {type.Name}.{member.MemberInfo.Name} is not optional, but has not been deserialized.");
                }
            }

            return(instance);
        }