Firstborn/Library/PackageCache/com.unity.addressables@1.19.19/Editor/Settings/KeyDataStore.cs

206 lines
7.7 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor.AddressableAssets.GUI;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Serialization;
namespace UnityEditor.AddressableAssets.Settings
{
/// <summary>
/// Contains serialized data in a generic serializable container.
/// </summary>
[Serializable]
public class KeyDataStore : ISerializationCallbackReceiver
{
[Serializable]
internal struct Entry
{
[FormerlySerializedAs("m_assemblyName")]
[SerializeField] string m_AssemblyName;
internal string AssemblyName { get { return m_AssemblyName; } set { m_AssemblyName = value; } }
[FormerlySerializedAs("m_className")]
[SerializeField] string m_ClassName;
internal string ClassName { get { return m_ClassName; } set { m_ClassName = value; } }
[FormerlySerializedAs("m_data")]
[SerializeField] string m_Data;
internal string Data { get { return m_Data; } set { m_Data = value; } }
[FormerlySerializedAs("m_key")]
[SerializeField] string m_Key;
internal string Key { get { return m_Key; } set { m_Key = value; } }
/// <inheritdoc/>
public override string ToString()
{
return Data;
}
}
internal void Reset()
{
m_SerializedData = null;
m_EntryMap = new Dictionary<string, object>();
}
[FormerlySerializedAs("m_serializedData")]
[SerializeField]
List<Entry> m_SerializedData;
Dictionary<string, object> m_EntryMap = new Dictionary<string, object>();
/// <summary>
/// Delegate that is invoked when data is modified.
/// </summary>
public Action<string, object, bool> OnSetData { get; set; }
/// <summary>
/// Implementation of ISerializationCallbackReceiver interface, used to convert data to a serializable form.
/// </summary>
public void OnBeforeSerialize()
{
m_SerializedData = new List<Entry>(m_EntryMap.Count);
foreach (var k in m_EntryMap)
m_SerializedData.Add(CreateEntry(k.Key, k.Value));
}
Entry CreateEntry(string key, object value)
{
var entry = new Entry();
entry.Key = key;
var objType = value.GetType();
entry.AssemblyName = objType.Assembly.FullName;
entry.ClassName = objType.FullName;
try
{
if (objType == typeof(string))
{
entry.Data = value as string;
}
else if (objType.IsEnum)
{
entry.Data = value.ToString();
}
else
{
var parseMethod = objType.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Any, new[] { typeof(string) }, null);
if (parseMethod == null || parseMethod.ReturnType != objType)
entry.Data = JsonUtility.ToJson(value);
else
entry.Data = value.ToString();
}
}
catch (Exception ex)
{
Addressables.LogWarningFormat("KeyDataStore unable to serizalize entry {0} with value {1}, exception: {2}", key, value, ex);
}
return entry;
}
object CreateObject(Entry e)
{
try
{
var assembly = Assembly.Load(e.AssemblyName);
var objType = assembly.GetType(e.ClassName);
if (objType == typeof(string))
return e.Data;
if (objType.IsEnum)
return Enum.Parse(objType, e.Data);
var parseMethod = objType.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Any, new[] { typeof(string) }, null);
if (parseMethod == null || parseMethod.ReturnType != objType)
return JsonUtility.FromJson(e.Data, objType);
return parseMethod.Invoke(null, new object[] { e.Data });
}
catch (Exception ex)
{
Addressables.LogWarningFormat("KeyDataStore unable to deserizalize entry {0} from assembly {1} of type {2}, exception: {3}", e.Key, e.AssemblyName, e.ClassName, ex);
return null;
}
}
/// <summary>
/// Implementation of ISerializationCallbackReceiver interface, used to convert data from its serializable form.
/// </summary>
public void OnAfterDeserialize()
{
m_EntryMap = new Dictionary<string, object>(m_SerializedData.Count);
foreach (var e in m_SerializedData)
m_EntryMap.Add(e.Key, CreateObject(e));
m_SerializedData = null;
}
/// <summary>
/// The collection of keys stored.
/// </summary>
public IEnumerable<string> Keys { get { return m_EntryMap.Keys; } }
/// <summary>
/// Set the value of a specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="data">The data to store. Supported types are strings, POD types, objects that have a static method named 'Parse' that convert a string to an object, and object that are serializable via JSONUtilty.</param>
public void SetData(string key, object data)
{
var isNew = m_EntryMap.ContainsKey(key);
m_EntryMap[key] = data;
if (OnSetData != null)
OnSetData(key, data, isNew);
}
/// <summary>
/// Set data for a specified key from a string.
/// </summary>
/// <param name="key">The data key.</param>
/// <param name="data">The data string value.</param>
public void SetDataFromString(string key, string data)
{
var existingType = GetDataType(key);
if (existingType == null)
SetData(key, data);
else
SetData(key, CreateObject(new Entry { AssemblyName = existingType.Assembly.FullName, ClassName = existingType.FullName, Data = data, Key = key }));
}
internal Type GetDataType(string key)
{
object val;
if (m_EntryMap.TryGetValue(key, out val))
return val.GetType();
return null;
}
internal string GetDataString(string key, string defaultValue)
{
object val;
if (m_EntryMap.TryGetValue(key, out val))
return CreateEntry(key, val).ToString();
return defaultValue;
}
/// <summary>
/// Get data via a specified key.
/// </summary>
/// <typeparam name="T">The data type.</typeparam>
/// <param name="key">The key.</param>
/// <param name="defaultValue">The default value to return if the data is not found.</param>
/// <param name="addDefault">Optional parameter to control whether to add the default value if the data is not found.</param>
/// <returns></returns>
public T GetData<T>(string key, T defaultValue, bool addDefault = false)
{
try
{
object val;
if (m_EntryMap.TryGetValue(key, out val))
return (T)val;
}
catch (Exception)
{
// ignored
}
if (addDefault)
SetData(key, defaultValue);
return defaultValue;
}
}
}