< Summary

Class:GDX.Collections.Generic.SerializableDictionary[TKey,TValue]
Assembly:GDX
File(s):D:/BuildAgent/work/GDX-Documentation/Projects/GDX_Development/Packages/com.dotbunny.gdx/GDX/Collections/Generic/SerializableDictionary.cs
Covered lines:45
Uncovered lines:18
Coverable lines:63
Total lines:207
Line coverage:71.4% (45 of 63)
Covered branches:0
Total branches:0
Covered methods:6
Total methods:8
Method coverage:75% (6 of 8)

Coverage History

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SerializableDictionary()0%220100%
GetSerializedDataLength()0%110100%
IsSerializableType(...)0%110100%
LoadSerializedData(...)0%6.896070.83%
OnAfterDeserialize()0%2100%
OnBeforeSerialize()0%2100%
OverwriteSerializedData(...)0%2.152066.67%
SaveSerializedData()0%3.013088.89%

File(s)

D:/BuildAgent/work/GDX-Documentation/Projects/GDX_Development/Packages/com.dotbunny.gdx/GDX/Collections/Generic/SerializableDictionary.cs

#LineLine coverage
 1// Copyright (c) 2020-2022 dotBunny Inc.
 2// dotBunny licenses this file to you under the BSL-1.0 license.
 3// See the LICENSE file in the project root for more information.
 4
 5#if !UNITY_DOTSRUNTIME
 6
 7using System;
 8using System.Collections.Generic;
 9using UnityEngine;
 10using UnityEngine.Serialization;
 11
 12namespace GDX.Collections.Generic
 13{
 14
 15#pragma warning disable IDE0049
 16    /// <summary>
 17    ///     A Unity serializable <see cref="Dictionary{TKey,TValue}" />.
 18    /// </summary>
 19    /// <remarks>
 20    ///     <para>
 21    ///         This will NOT work with <see cref="System.Object" /> based objects, use <see cref="UnityEngine.Object" /
 22    ///         you must. While .NET has solutions for creating custom serialization paths, Unity uses its own system to
 23    ///         serialize data into YAML structures. This also assumes that the types provided can be serialized by Unit
 24    ///     </para>
 25    ///     <para>
 26    ///         The process of serializing and deserializing this dictionary should not be considered performant.
 27    ///     </para>
 28    /// </remarks>
 29    /// <typeparam name="TKey">The dictionary's key <see cref="Type" />.</typeparam>
 30    /// <typeparam name="TValue">The dictionary's value <see cref="Type" />.</typeparam>
 31    /// <exception cref="UnsupportedRuntimeException">Not supported on DOTS Runtime.</exception>
 32    [Serializable]
 33#pragma warning restore IDE0049
 34    [VisualScriptingCompatible(1)]
 35    public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
 36    {
 37#pragma warning disable IDE1006
 38        // ReSharper disable InconsistentNaming
 39
 40        /// <summary>
 41        ///     Is the dictionary completely capable of being serialized by Unity?
 42        /// </summary>
 43        /// <remarks>This field is determined/cached in the constructor.</remarks>
 44        [FormerlySerializedAs("isSerializable")]
 45
 46        [HideInInspector] [SerializeField] bool m_IsSerializable;
 47
 48        /// <summary>
 49        ///     The length of the serialized data arrays.
 50        /// </summary>
 51        [FormerlySerializedAs("serializedLength")]
 352        [HideInInspector] [SerializeField] int m_SerializedLength = -1;
 53
 54        /// <summary>
 55        ///     An array of all of the keys, in order, used to recreate the base <see cref="Dictionary{TKey,TValue}" />.
 56        /// </summary>
 57        [FormerlySerializedAs("serializedKeys")]
 58        [HideInInspector] [SerializeField] TKey[] m_SerializedKeys;
 59
 60        /// <summary>
 61        ///     An array of all of the values, in order, used to recreate the base <see cref="Dictionary{TKey,TValue}" /
 62        /// </summary>
 63        [FormerlySerializedAs("serializedValues")]
 64        [HideInInspector] [SerializeField] TValue[] m_SerializedValues;
 65
 66        // ReSharper restore InconsistentNaming
 67#pragma warning restore IDE1006
 68
 69        /// <summary>
 70        ///     Type constructor.
 71        /// </summary>
 372        public SerializableDictionary()
 373        {
 74#if UNITY_EDITOR
 375            m_IsSerializable = IsSerializableType(typeof(TKey)) && IsSerializableType(typeof(TValue));
 76#endif
 377        }
 78
 79        /// <summary>
 80        ///     Get the length of the serialized data arrays.
 81        /// </summary>
 82        /// <returns>An integer value representing the count.</returns>
 83        public int GetSerializedDataLength()
 284        {
 285            return m_SerializedLength;
 286        }
 87
 88        /// <summary>
 89        ///     Is the <paramref name="type" /> capable of being serialized by the
 90        ///     <see cref="SerializableDictionary{TKey,TValue}" />, utilizing Unity's own serialization system?
 91        /// </summary>
 92        /// <returns>true/false if the type is valid.</returns>
 93        public static bool IsSerializableType(Type type)
 894        {
 895            return type != typeof(object);
 896        }
 97
 98        /// <summary>
 99        ///     Load the data into the <see cref="Dictionary{TKey,TValue}" /> cached in the serialized data.
 100        /// </summary>
 101        /// <param name="clearAfterLoad">Should the serialized data be cleared after loading?</param>
 102        public void LoadSerializedData(bool clearAfterLoad = true)
 1103        {
 1104            Clear();
 105
 106            // If this is not serializable we need to do nothing
 1107            if (!m_IsSerializable || m_SerializedLength <= 0)
 0108            {
 0109                return;
 110            }
 111
 112            // Iterate over all the serialized data and put it back into the dictionary as it once was, in order.
 6113            for (int i = 0; i < m_SerializedLength; i++)
 2114            {
 115#if UNITY_EDITOR
 116                // If the key is already in the dataset what do we do?
 2117                if (ContainsKey(m_SerializedKeys[i]))
 0118                {
 0119                    Trace.Output(Trace.TraceLevel.Error, "A duplicate key has been detected in the serialized dictionary
 0120                }
 121                else
 2122                {
 123#endif
 2124                    Add(m_SerializedKeys[i], m_SerializedValues[i]);
 125#if UNITY_EDITOR
 2126                }
 127#endif
 2128            }
 129
 130            // Remove any data cached so that references are not held.
 1131            if (!clearAfterLoad)
 0132            {
 0133                return;
 134            }
 135
 1136            m_SerializedLength = -1;
 1137            m_SerializedKeys = null;
 1138            m_SerializedValues = null;
 1139        }
 140
 141        /// <summary>
 142        ///     Rehydrate the serialized data arrays back into a cohesive <see cref="Dictionary{TKey,TValue}" />.
 143        /// </summary>
 144        /// <remarks>Invoked by Unity, calls <see cref="LoadSerializedData" />.</remarks>
 145        public void OnAfterDeserialize()
 0146        {
 0147            LoadSerializedData();
 0148        }
 149
 150        /// <summary>
 151        ///     Build out serialized data arrays and associative data, used to rehydrate during deserialization.
 152        /// </summary>
 153        /// <remarks>Invoked by Unity, calls <see cref="SaveSerializedData" />.</remarks>
 154        public void OnBeforeSerialize()
 0155        {
 0156            SaveSerializedData();
 0157        }
 158
 159        /// <summary>
 160        ///     Overwrite data in the serialized arrays with the provided data.
 161        /// </summary>
 162        /// <param name="keyArray">An array of keys.</param>
 163        /// <param name="valueArray">An array of values.</param>
 164        public void OverwriteSerializedData(TKey[] keyArray, TValue[] valueArray)
 1165        {
 1166            if (keyArray.Length != valueArray.Length)
 0167            {
 0168                Trace.Output(Trace.TraceLevel.Error,"The provided array lengths must match.");
 0169                return;
 170            }
 171
 1172            m_SerializedKeys = keyArray;
 1173            m_SerializedValues = valueArray;
 1174            m_SerializedLength = keyArray.Length;
 1175        }
 176
 177        /// <summary>
 178        ///     Fill serializable arrays from dictionary data.
 179        /// </summary>
 180        /// <remarks>We will always create the arrays so the property drawers function nicely.</remarks>
 181        public void SaveSerializedData()
 2182        {
 183            // If this is not serializable we need to do nothing
 2184            if (!m_IsSerializable)
 0185            {
 0186                return;
 187            }
 188
 189            // Stash our length for future usage
 2190            m_SerializedLength = Count;
 191
 192            // Create our serialized data arrays
 2193            m_SerializedKeys = new TKey[m_SerializedLength];
 2194            m_SerializedValues = new TValue[m_SerializedLength];
 195
 196            // Stash our values
 2197            int index = 0;
 10198            foreach (KeyValuePair<TKey, TValue> pair in this)
 2199            {
 2200                m_SerializedKeys[index] = pair.Key;
 2201                m_SerializedValues[index] = pair.Value;
 2202                index++;
 2203            }
 2204        }
 205    }
 206}
 207#endif