csharp-sdk-upm/Storage/Source/Internal/Storage/Unity/StorageController.cs

251 lines
7.9 KiB
C#

using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using System.Threading;
namespace LeanCloud.Storage.Internal
{
/// <summary>
/// Implements `IStorageController` for PCL targets, based off of PCLStorage.
/// </summary>
public class StorageController : IStorageController
{
private const string LeanCloudStorageFileName = "LeanCloud.settings";
private TaskQueue taskQueue = new TaskQueue();
private string settingsPath;
private StorageDictionary storageDictionary;
private bool isWebPlayer;
private class StorageDictionary : IStorageDictionary<string, object>
{
private object mutex;
private Dictionary<string, object> dictionary;
private string settingsPath;
private bool isWebPlayer;
public StorageDictionary(string settingsPath, bool isWebPlayer)
{
this.settingsPath = settingsPath;
this.isWebPlayer = isWebPlayer;
mutex = new object();
dictionary = new Dictionary<string, object>();
}
internal Task SaveAsync()
{
string jsonEncoded;
lock (mutex)
{
jsonEncoded = Json.Encode(dictionary);
}
if (this.isWebPlayer)
{
PlayerPrefs.SetString(LeanCloudStorageFileName, jsonEncoded);
PlayerPrefs.Save();
}
else if (Application.platform == RuntimePlatform.tvOS)
{
Debug.Log("Running on TvOS, prefs cannot be saved.");
}
else
{
using (var fs = new FileStream(settingsPath, FileMode.Create, FileAccess.Write))
{
using (var writer = new StreamWriter(fs))
{
writer.Write(jsonEncoded);
}
}
}
return Task.FromResult<object>(null);
}
internal Task LoadAsync()
{
string jsonString = null;
try
{
if (this.isWebPlayer)
{
jsonString = PlayerPrefs.GetString(LeanCloudStorageFileName, null);
}
else if (Application.platform == RuntimePlatform.tvOS)
{
Debug.Log("Running on TvOS, prefs cannot be loaded.");
}
else
{
using (var fs = new FileStream(settingsPath, FileMode.Open, FileAccess.Read))
{
var reader = new StreamReader(fs);
jsonString = reader.ReadToEnd();
}
}
}
catch (Exception)
{
// Do nothing
}
if (jsonString == null)
{
lock (mutex)
{
dictionary = new Dictionary<string, object>();
return Task.FromResult<object>(null);
}
}
Dictionary<string, object> decoded = Json.Parse(jsonString) as Dictionary<string, object>;
lock (mutex)
{
dictionary = decoded ?? new Dictionary<string, object>();
return Task.FromResult<object>(null);
}
}
internal void Update(IDictionary<string, object> contents)
{
lock (mutex)
{
dictionary = contents.ToDictionary(p => p.Key, p => p.Value);
}
}
public Task AddAsync(string key, object value)
{
lock (mutex)
{
dictionary[key] = value;
}
return SaveAsync();
}
public Task RemoveAsync(string key)
{
lock (mutex)
{
dictionary.Remove(key);
}
return SaveAsync();
}
public bool ContainsKey(string key)
{
lock (mutex)
{
return dictionary.ContainsKey(key);
}
}
public IEnumerable<string> Keys
{
get { lock (mutex) { return dictionary.Keys; } }
}
public bool TryGetValue(string key, out object value)
{
lock (mutex)
{
return dictionary.TryGetValue(key, out value);
}
}
public IEnumerable<object> Values
{
get { lock (mutex) { return dictionary.Values; } }
}
public object this[string key]
{
get { lock (mutex) { return dictionary[key]; } }
}
public int Count
{
get { lock (mutex) { return dictionary.Count; } }
}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
lock (mutex)
{
return dictionary.GetEnumerator();
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
lock (mutex)
{
return dictionary.GetEnumerator();
}
}
}
public StorageController()
: this(Path.Combine(Application.persistentDataPath, LeanCloudStorageFileName), false)
{
}
public StorageController(String settingsPath)
: this(settingsPath, false)
{
}
public StorageController(bool isWebPlayer, string fileNamePrefix)
: this(Path.Combine(Application.persistentDataPath, string.Format("{0}_{1}", fileNamePrefix, LeanCloudStorageFileName)), isWebPlayer)
{
}
public StorageController(string settingsPath, bool isWebPlayer)
{
this.settingsPath = settingsPath;
this.isWebPlayer = isWebPlayer;
}
public Task<IStorageDictionary<string, object>> LoadAsync()
{
return taskQueue.Enqueue(toAwait =>
{
return toAwait.ContinueWith(_ =>
{
if (storageDictionary != null)
{
return Task.FromResult<IStorageDictionary<string, object>>(storageDictionary);
}
storageDictionary = new StorageDictionary(settingsPath, this.isWebPlayer);
return storageDictionary.LoadAsync().OnSuccess(__ => storageDictionary as IStorageDictionary<string, object>);
}).Unwrap();
}, CancellationToken.None);
}
public Task<IStorageDictionary<string, object>> SaveAsync(IDictionary<string, object> contents)
{
return taskQueue.Enqueue(toAwait =>
{
return toAwait.ContinueWith(_ =>
{
if (storageDictionary == null)
{
storageDictionary = new StorageDictionary(settingsPath, this.isWebPlayer);
}
storageDictionary.Update(contents);
return storageDictionary.SaveAsync().OnSuccess(__ => storageDictionary as IStorageDictionary<string, object>);
}).Unwrap();
}, CancellationToken.None);
}
}
}