using LeanCloud.Storage.Internal; using System; using System.Threading; using System.Threading.Tasks; namespace LeanCloud.Storage.Internal { public class InstallationIdController : IInstallationIdController { private const string InstallationIdKey = "InstallationId"; private readonly object mutex = new object(); private Guid? installationId; private readonly IStorageController storageController; public InstallationIdController(IStorageController storageController) { this.storageController = storageController; } public Task SetAsync(Guid? installationId) { lock (mutex) { Task saveTask; if (installationId == null) { saveTask = storageController .LoadAsync() .OnSuccess(storage => storage.Result.RemoveAsync(InstallationIdKey)) .Unwrap(); } else { saveTask = storageController .LoadAsync() .OnSuccess(storage => storage.Result.AddAsync(InstallationIdKey, installationId.ToString())) .Unwrap(); } this.installationId = installationId; return saveTask; } } public Task GetAsync() { lock (mutex) { if (installationId != null) { return Task.FromResult(installationId); } } return storageController .LoadAsync() .OnSuccess, Task>(s => { object id; s.Result.TryGetValue(InstallationIdKey, out id); try { lock (mutex) { installationId = new Guid((string)id); return Task.FromResult(installationId); } } catch (Exception) { var newInstallationId = Guid.NewGuid(); return SetAsync(newInstallationId).OnSuccess(_ => newInstallationId); } }) .Unwrap(); } public Task ClearAsync() { return SetAsync(null); } } }