diff --git a/Storage/Storage/Internal/AVCorePlugins.cs b/Storage/Storage/Internal/AVCorePlugins.cs index 3b2fd06..9e65d8c 100644 --- a/Storage/Storage/Internal/AVCorePlugins.cs +++ b/Storage/Storage/Internal/AVCorePlugins.cs @@ -1,65 +1,45 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using LeanCloud.Storage.Internal; - -namespace LeanCloud.Storage.Internal -{ - public class AVPlugins : IAVCorePlugins - { + +namespace LeanCloud.Storage.Internal { + public class AVPlugins { private static readonly object instanceMutex = new object(); - private static IAVCorePlugins instance; - public static IAVCorePlugins Instance - { - get - { - lock (instanceMutex) - { + private static AVPlugins instance; + public static AVPlugins Instance { + get { + lock (instanceMutex) { instance = instance ?? new AVPlugins(); return instance; } } - set - { - lock (instanceMutex) - { - instance = value; - } - } } private readonly object mutex = new object(); #region Server Controllers - private IHttpClient httpClient; - private IAppRouterController appRouterController; - private IAVCommandRunner commandRunner; - private IStorageController storageController; + private HttpClient httpClient; + private AppRouterController appRouterController; + private AVCommandRunner commandRunner; + private StorageController storageController; - private IAVCloudCodeController cloudCodeController; - private IAVConfigController configController; - private IAVFileController fileController; - private IAVObjectController objectController; - private IAVQueryController queryController; - private IAVSessionController sessionController; - private IAVUserController userController; - private IObjectSubclassingController subclassingController; + private AVCloudCodeController cloudCodeController; + private AVFileController fileController; + private AVObjectController objectController; + private AVQueryController queryController; + private AVSessionController sessionController; + private AVUserController userController; + private ObjectSubclassingController subclassingController; #endregion #region Current Instance Controller - private IAVCurrentUserController currentUserController; - private IInstallationIdController installationIdController; + private AVCurrentUserController currentUserController; + private InstallationIdController installationIdController; #endregion - public void Reset() - { - lock (mutex) - { + public void Reset() { + lock (mutex) { HttpClient = null; AppRouterController = null; CommandRunner = null; @@ -77,305 +57,217 @@ namespace LeanCloud.Storage.Internal } } - public IHttpClient HttpClient - { - get - { - lock (mutex) - { + public HttpClient HttpClient { + get { + lock (mutex) { httpClient = httpClient ?? new HttpClient(); return httpClient; } } - set - { - lock (mutex) - { + set { + lock (mutex) { httpClient = value; } } } - public IAppRouterController AppRouterController - { - get - { - lock (mutex) - { + public AppRouterController AppRouterController { + get { + lock (mutex) { appRouterController = appRouterController ?? new AppRouterController(); return appRouterController; } } - set - { - lock (mutex) - { + set { + lock (mutex) { appRouterController = value; } } } - public IAVCommandRunner CommandRunner - { - get - { - lock (mutex) - { - commandRunner = commandRunner ?? new AVCommandRunner(HttpClient, InstallationIdController); + public AVCommandRunner CommandRunner { + get { + lock (mutex) { + commandRunner = commandRunner ?? new AVCommandRunner(); return commandRunner; } } - set - { - lock (mutex) - { + set { + lock (mutex) { commandRunner = value; } } } -#if !UNITY - public IStorageController StorageController - { - get - { - lock (mutex) - { - storageController = storageController ?? new StorageController(AVClient.CurrentConfiguration.ApplicationId); - return storageController; - } - } - set - { - lock (mutex) - { - storageController = value; - } - } - } -#endif #if UNITY - public IStorageController StorageController - { - get - { - lock (mutex) - { + public StorageController StorageController { + get { + lock (mutex) { storageController = storageController ?? new StorageController(AVInitializeBehaviour.IsWebPlayer, AVClient.CurrentConfiguration.ApplicationId); return storageController; } } - set - { - lock (mutex) - { + set { + lock (mutex) { + storageController = value; + } + } + } +#else + public StorageController StorageController { + get { + lock (mutex) { + storageController = storageController ?? new StorageController(AVClient.CurrentConfiguration.ApplicationId); + return storageController; + } + } + set { + lock (mutex) { storageController = value; } } } #endif - public IAVCloudCodeController CloudCodeController - { - get - { - lock (mutex) - { - cloudCodeController = cloudCodeController ?? new AVCloudCodeController(CommandRunner); + public AVCloudCodeController CloudCodeController { + get { + lock (mutex) { + cloudCodeController = cloudCodeController ?? new AVCloudCodeController(); return cloudCodeController; } } - set - { - lock (mutex) - { + set { + lock (mutex) { cloudCodeController = value; } } } - public IAVFileController FileController - { - get - { - lock (mutex) - { - if (AVClient.CurrentConfiguration.RegionValue == 0) - fileController = fileController ?? new QiniuFileController(CommandRunner); - else if (AVClient.CurrentConfiguration.RegionValue == 2) - fileController = fileController ?? new QCloudCosFileController(CommandRunner); - else if (AVClient.CurrentConfiguration.RegionValue == 1) - fileController = fileController ?? new AWSS3FileController(CommandRunner); - + public AVFileController FileController { + get { + if (fileController != null) { + return fileController; + } + lock (mutex) { + switch (AVClient.CurrentConfiguration.RegionValue) { + case 0: + fileController = new QiniuFileController(); + break; + case 2: + fileController = new QCloudCosFileController(); + break; + case 1: + fileController = new AWSS3FileController(); + break; + } return fileController; } } - set - { - lock (mutex) - { + set { + lock (mutex) { fileController = value; } } } - public IAVConfigController ConfigController - { - get - { - lock (mutex) - { - if (configController == null) - { - configController = new AVConfigController(CommandRunner, StorageController); - } - return configController; - } - } - set - { - lock (mutex) - { - configController = value; - } - } - } - - public IAVObjectController ObjectController - { - get - { - lock (mutex) - { - objectController = objectController ?? new AVObjectController(CommandRunner); + public AVObjectController ObjectController { + get { + lock (mutex) { + objectController = objectController ?? new AVObjectController(); return objectController; } } - set - { - lock (mutex) - { + set { + lock (mutex) { objectController = value; } } } - public IAVQueryController QueryController - { - get - { - lock (mutex) - { - if (queryController == null) - { - queryController = new AVQueryController(CommandRunner); + public AVQueryController QueryController { + get { + lock (mutex) { + if (queryController == null) { + queryController = new AVQueryController(); } return queryController; } } - set - { - lock (mutex) - { + set { + lock (mutex) { queryController = value; } } } - public IAVSessionController SessionController - { - get - { - lock (mutex) - { - sessionController = sessionController ?? new AVSessionController(CommandRunner); + public AVSessionController SessionController { + get { + lock (mutex) { + sessionController = sessionController ?? new AVSessionController(); return sessionController; } } - set - { - lock (mutex) - { + set { + lock (mutex) { sessionController = value; } } } - public IAVUserController UserController - { - get - { - lock (mutex) - { - userController = userController ?? new AVUserController(CommandRunner); + public AVUserController UserController { + get { + lock (mutex) { + userController = userController ?? new AVUserController(); return userController; } } - set - { - lock (mutex) - { + set { + lock (mutex) { userController = value; } } } - public IAVCurrentUserController CurrentUserController - { - get - { - lock (mutex) - { - currentUserController = currentUserController ?? new AVCurrentUserController(StorageController); + public AVCurrentUserController CurrentUserController { + get { + lock (mutex) { + currentUserController = currentUserController ?? new AVCurrentUserController(); return currentUserController; } } - set - { - lock (mutex) - { + set { + lock (mutex) { currentUserController = value; } } } - public IObjectSubclassingController SubclassingController - { - get - { - lock (mutex) - { - if (subclassingController == null) - { + public ObjectSubclassingController SubclassingController { + get { + lock (mutex) { + if (subclassingController == null) { subclassingController = new ObjectSubclassingController(); subclassingController.AddRegisterHook(typeof(AVUser), () => CurrentUserController.ClearFromMemory()); } return subclassingController; } } - set - { - lock (mutex) - { + set { + lock (mutex) { subclassingController = value; } } } - public IInstallationIdController InstallationIdController - { - get - { - lock (mutex) - { - installationIdController = installationIdController ?? new InstallationIdController(StorageController); + public InstallationIdController InstallationIdController { + get { + lock (mutex) { + installationIdController = installationIdController ?? new InstallationIdController(); return installationIdController; } } - set - { - lock (mutex) - { + set { + lock (mutex) { installationIdController = value; } } diff --git a/Storage/Storage/Internal/AppRouter/AppRouterController.cs b/Storage/Storage/Internal/AppRouter/AppRouterController.cs index ed554d9..d8ce0e9 100644 --- a/Storage/Storage/Internal/AppRouter/AppRouterController.cs +++ b/Storage/Storage/Internal/AppRouter/AppRouterController.cs @@ -6,17 +6,11 @@ using System.Threading.Tasks; using Newtonsoft.Json; using System.Net.Http; -namespace LeanCloud.Storage.Internal -{ - public class AppRouterController : IAppRouterController - { +namespace LeanCloud.Storage.Internal { + public class AppRouterController { private AppRouterState currentState; private readonly ReaderWriterLockSlim locker = new ReaderWriterLockSlim(); - /// - /// Get current app's router state - /// - /// public AppRouterState Get() { if (string.IsNullOrEmpty(AVClient.CurrentConfiguration.ApplicationId)) { throw new AVException(AVException.ErrorCode.NotInitialized, "ApplicationId can not be null."); diff --git a/Storage/Storage/Internal/AppRouter/AppRouterState.cs b/Storage/Storage/Internal/AppRouter/AppRouterState.cs index 61438ed..531ba91 100644 --- a/Storage/Storage/Internal/AppRouter/AppRouterState.cs +++ b/Storage/Storage/Internal/AppRouter/AppRouterState.cs @@ -47,21 +47,12 @@ namespace LeanCloud.Storage.Internal FetchedAt = DateTime.Now; } - /// - /// Is this app router state expired. - /// public bool IsExpired { get { return DateTime.Now > FetchedAt + TimeSpan.FromSeconds(TTL); } } - /// - /// Get the initial usable router state - /// - /// Current app's appId - /// Current app's region - /// Initial app router state public static AppRouterState GetFallbackServers(string appId, AVClient.Configuration.AVRegion region) { var regionValue = (int)region; var prefix = appId.Substring(0, 8).ToLower(); diff --git a/Storage/Storage/Internal/AppRouter/IAppRouterController.cs b/Storage/Storage/Internal/AppRouter/IAppRouterController.cs deleted file mode 100644 index 24c3366..0000000 --- a/Storage/Storage/Internal/AppRouter/IAppRouterController.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal -{ - public interface IAppRouterController - { - AppRouterState Get(); - Task QueryAsync(CancellationToken cancellationToken); - void Clear(); - } -} diff --git a/Storage/Storage/Internal/Cloud/Controller/AVCloudCodeController.cs b/Storage/Storage/Internal/Cloud/Controller/AVCloudCodeController.cs index 0b3745e..3850752 100644 --- a/Storage/Storage/Internal/Cloud/Controller/AVCloudCodeController.cs +++ b/Storage/Storage/Internal/Cloud/Controller/AVCloudCodeController.cs @@ -7,15 +7,8 @@ using System.Net.Http; namespace LeanCloud.Storage.Internal { - public class AVCloudCodeController : IAVCloudCodeController + public class AVCloudCodeController { - private readonly IAVCommandRunner commandRunner; - - public AVCloudCodeController(IAVCommandRunner commandRunner) - { - this.commandRunner = commandRunner; - } - public Task CallFunctionAsync(String name, IDictionary parameters, string sessionToken, @@ -26,7 +19,7 @@ namespace LeanCloud.Storage.Internal Method = HttpMethod.Post, Content = parameters }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary; if (!decoded.ContainsKey("result")) @@ -44,7 +37,7 @@ namespace LeanCloud.Storage.Internal Method = HttpMethod.Post, Content = parameters }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary; if (!decoded.ContainsKey("result")) diff --git a/Storage/Storage/Internal/Cloud/Controller/IAVCloudCodeController.cs b/Storage/Storage/Internal/Cloud/Controller/IAVCloudCodeController.cs deleted file mode 100644 index ad6138f..0000000 --- a/Storage/Storage/Internal/Cloud/Controller/IAVCloudCodeController.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal -{ - public interface IAVCloudCodeController - { - Task CallFunctionAsync(String name, - IDictionary parameters, - string sessionToken, - CancellationToken cancellationToken); - - Task RPCFunction(string name, IDictionary parameters, - string sessionToken, - CancellationToken cancellationToken); - } -} diff --git a/Storage/Storage/Internal/Command/AVCommandRunner.cs b/Storage/Storage/Internal/Command/AVCommandRunner.cs index c2c84d9..56172c0 100644 --- a/Storage/Storage/Internal/Command/AVCommandRunner.cs +++ b/Storage/Storage/Internal/Command/AVCommandRunner.cs @@ -7,29 +7,15 @@ using System.Threading; using System.Threading.Tasks; using System.Text; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -namespace LeanCloud.Storage.Internal -{ +namespace LeanCloud.Storage.Internal { /// /// Command Runner. /// - public class AVCommandRunner : IAVCommandRunner { + public class AVCommandRunner { public const string APPLICATION_JSON = "application/json"; - private readonly System.Net.Http.HttpClient httpClient; - private readonly IInstallationIdController installationIdController; - - /// - /// - /// - /// - /// - public AVCommandRunner(IHttpClient httpClient, IInstallationIdController installationIdController) - { - this.httpClient = new System.Net.Http.HttpClient(); - this.installationIdController = installationIdController; - } + private readonly System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient(); /// /// @@ -43,7 +29,7 @@ namespace LeanCloud.Storage.Internal IProgress uploadProgress = null, IProgress downloadProgress = null, CancellationToken cancellationToken = default) { - + var request = new HttpRequestMessage { RequestUri = command.Uri, Method = command.Method, @@ -67,7 +53,7 @@ namespace LeanCloud.Storage.Internal PrintResponse(response, resultString); var ret = new Tuple(response.StatusCode, resultString); - + var responseCode = ret.Item1; var contentString = ret.Item2; @@ -105,7 +91,7 @@ namespace LeanCloud.Storage.Internal async Task> GetHeadersAsync() { var headers = new Dictionary(); - var installationId = await installationIdController.GetAsync(); + var installationId = await AVPlugins.Instance.InstallationIdController.GetAsync(); headers.Add("X-LC-Installation-Id", installationId.ToString()); var conf = AVClient.CurrentConfiguration; headers.Add("X-LC-Id", conf.ApplicationId); diff --git a/Storage/Storage/Internal/Command/IAVCommandRunner.cs b/Storage/Storage/Internal/Command/IAVCommandRunner.cs deleted file mode 100644 index f2dc362..0000000 --- a/Storage/Storage/Internal/Command/IAVCommandRunner.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal -{ - public interface IAVCommandRunner - { - /// - /// Executes and convert the result into Dictionary. - /// - /// The command to be run. - /// Upload progress callback. - /// Download progress callback. - /// The cancellation token for the request. - /// - Task> RunCommandAsync(AVCommand command, - IProgress uploadProgress = null, - IProgress downloadProgress = null, - CancellationToken cancellationToken = default(CancellationToken)); - } -} diff --git a/Storage/Storage/Internal/Config/Controller/AVConfigController.cs b/Storage/Storage/Internal/Config/Controller/AVConfigController.cs deleted file mode 100644 index a24f8c8..0000000 --- a/Storage/Storage/Internal/Config/Controller/AVConfigController.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Threading; -using System.Net.Http; - -namespace LeanCloud.Storage.Internal { - /// - /// Config controller. - /// - internal class AVConfigController : IAVConfigController { - private readonly IAVCommandRunner commandRunner; - - /// - /// Initializes a new instance of the class. - /// - public AVConfigController(IAVCommandRunner commandRunner, IStorageController storageController) { - this.commandRunner = commandRunner; - CurrentConfigController = new AVCurrentConfigController(storageController); - } - - public IAVCommandRunner CommandRunner { get; internal set; } - public IAVCurrentConfigController CurrentConfigController { get; internal set; } - - public Task FetchConfigAsync(String sessionToken, CancellationToken cancellationToken) { - var command = new AVCommand { - Path = "config", - Method = HttpMethod.Post, - }; - - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(task => { - cancellationToken.ThrowIfCancellationRequested(); - return new AVConfig(task.Result.Item2); - }).OnSuccess(task => { - cancellationToken.ThrowIfCancellationRequested(); - CurrentConfigController.SetCurrentConfigAsync(task.Result); - return task; - }).Unwrap(); - } - } -} diff --git a/Storage/Storage/Internal/Config/Controller/AVCurrentConfigController.cs b/Storage/Storage/Internal/Config/Controller/AVCurrentConfigController.cs deleted file mode 100644 index 2d97a58..0000000 --- a/Storage/Storage/Internal/Config/Controller/AVCurrentConfigController.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System.Threading.Tasks; -using System.Threading; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace LeanCloud.Storage.Internal { - /// - /// LeanCloud current config controller. - /// - internal class AVCurrentConfigController : IAVCurrentConfigController { - private const string CurrentConfigKey = "CurrentConfig"; - - private readonly TaskQueue taskQueue; - private AVConfig currentConfig; - - private IStorageController storageController; - - /// - /// Initializes a new instance of the class. - /// - public AVCurrentConfigController(IStorageController storageController) { - this.storageController = storageController; - - taskQueue = new TaskQueue(); - } - - public Task GetCurrentConfigAsync() { - return taskQueue.Enqueue(toAwait => toAwait.ContinueWith(_ => { - if (currentConfig == null) { - return storageController.LoadAsync().OnSuccess(t => { - object tmp; - t.Result.TryGetValue(CurrentConfigKey, out tmp); - - string propertiesString = tmp as string; - if (propertiesString != null) { - var dictionary = JsonConvert.DeserializeObject>(propertiesString); - currentConfig = new AVConfig(dictionary); - } else { - currentConfig = new AVConfig(); - } - - return currentConfig; - }); - } - - return Task.FromResult(currentConfig); - }), CancellationToken.None).Unwrap(); - } - - public Task SetCurrentConfigAsync(AVConfig config) { - return taskQueue.Enqueue(toAwait => toAwait.ContinueWith(_ => { - currentConfig = config; - - var jsonObject = ((IJsonConvertible)config).ToJSON(); - var jsonString = JsonConvert.SerializeObject(jsonObject); - - return storageController.LoadAsync().OnSuccess(t => t.Result.AddAsync(CurrentConfigKey, jsonString)); - }).Unwrap().Unwrap(), CancellationToken.None); - } - - public Task ClearCurrentConfigAsync() { - return taskQueue.Enqueue(toAwait => toAwait.ContinueWith(_ => { - currentConfig = null; - - return storageController.LoadAsync().OnSuccess(t => t.Result.RemoveAsync(CurrentConfigKey)); - }).Unwrap().Unwrap(), CancellationToken.None); - } - - public Task ClearCurrentConfigInMemoryAsync() { - return taskQueue.Enqueue(toAwait => toAwait.ContinueWith(_ => { - currentConfig = null; - }), CancellationToken.None); - } - } -} diff --git a/Storage/Storage/Internal/Config/Controller/IAVConfigController.cs b/Storage/Storage/Internal/Config/Controller/IAVConfigController.cs deleted file mode 100644 index 5cef0ac..0000000 --- a/Storage/Storage/Internal/Config/Controller/IAVConfigController.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Threading.Tasks; -using System.Threading; - -namespace LeanCloud.Storage.Internal { - public interface IAVConfigController { - /// - /// Gets the current config controller. - /// - /// The current config controller. - IAVCurrentConfigController CurrentConfigController { get; } - - /// - /// Fetches the config from the server asynchronously. - /// - /// The config async. - /// Session token. - /// Cancellation token. - Task FetchConfigAsync(String sessionToken, CancellationToken cancellationToken); - } -} diff --git a/Storage/Storage/Internal/Config/Controller/IAVCurrentConfigController.cs b/Storage/Storage/Internal/Config/Controller/IAVCurrentConfigController.cs deleted file mode 100644 index 759329c..0000000 --- a/Storage/Storage/Internal/Config/Controller/IAVCurrentConfigController.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal { - public interface IAVCurrentConfigController { - /// - /// Gets the current config async. - /// - /// The current config async. - Task GetCurrentConfigAsync(); - - /// - /// Sets the current config async. - /// - /// The current config async. - /// Config. - Task SetCurrentConfigAsync(AVConfig config); - - /// - /// Clears the current config async. - /// - /// The current config async. - Task ClearCurrentConfigAsync(); - - /// - /// Clears the current config in memory async. - /// - /// The current config in memory async. - Task ClearCurrentConfigInMemoryAsync(); - } -} diff --git a/Storage/Storage/Internal/File/Controller/AVFileController.cs b/Storage/Storage/Internal/File/Controller/AVFileController.cs index aa79596..735fe40 100644 --- a/Storage/Storage/Internal/File/Controller/AVFileController.cs +++ b/Storage/Storage/Internal/File/Controller/AVFileController.cs @@ -2,29 +2,17 @@ using System.IO; using System.Threading; using System.Threading.Tasks; -using LeanCloud.Storage.Internal; using System.Net; using System.Net.Http; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; -namespace LeanCloud.Storage.Internal -{ +namespace LeanCloud.Storage.Internal { /// /// AVF ile controller. /// - public class AVFileController : IAVFileController - { - protected readonly IAVCommandRunner commandRunner; - /// - /// Initializes a new instance of the class. - /// - /// Command runner. - public AVFileController(IAVCommandRunner commandRunner) - { - this.commandRunner = commandRunner; - } + public class AVFileController { /// /// Saves the async. /// @@ -65,16 +53,14 @@ namespace LeanCloud.Storage.Internal MimeType = state.MimeType }; } - public Task DeleteAsync(FileState state, string sessionToken, CancellationToken cancellationToken) - { + public Task DeleteAsync(FileState state, string sessionToken, CancellationToken cancellationToken) { var command = new AVCommand { Path = $"files/{state.ObjectId}", Method = HttpMethod.Delete }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken); + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken); } - internal Task>> GetFileToken(FileState fileState, CancellationToken cancellationToken) - { + internal Task>> GetFileToken(FileState fileState, CancellationToken cancellationToken) { Task>> rtn; string currentSessionToken = AVUser.CurrentSessionToken; string str = fileState.Name; @@ -90,44 +76,38 @@ namespace LeanCloud.Storage.Internal Method = HttpMethod.Post, Content = parameters }; - return commandRunner.RunCommandAsync>(command); + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command); } - public Task GetAsync(string objectId, string sessionToken, CancellationToken cancellationToken) - { + public Task GetAsync(string objectId, string sessionToken, CancellationToken cancellationToken) { var command = new AVCommand { Path = $"files/{objectId}", Method = HttpMethod.Get }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(_ => - { + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(_ => { var result = _.Result; var jsonData = result.Item2; cancellationToken.ThrowIfCancellationRequested(); - return new FileState - { + return new FileState { ObjectId = jsonData["objectId"] as string, Name = jsonData["name"] as string, Url = new Uri(jsonData["url"] as string, UriKind.Absolute), }; }); } - internal static string GetUniqueName(FileState fileState) - { + internal static string GetUniqueName(FileState fileState) { string key = Random(12); string extension = Path.GetExtension(fileState.Name); key += extension; fileState.CloudName = key; return key; } - internal static string Random(int length) - { + internal static string Random(int length) { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; var random = new Random(); return new string(Enumerable.Repeat(chars, length) .Select(s => s[random.Next(s.Length)]).ToArray()); } - internal static double CalcProgress(double already, double total) - { + internal static double CalcProgress(double already, double total) { var pv = (1.0 * already / total); return Math.Round(pv, 3); } diff --git a/Storage/Storage/Internal/File/Controller/AWSS3FileController.cs b/Storage/Storage/Internal/File/Controller/AWSS3FileController.cs index 92a5fbe..5ad00f6 100644 --- a/Storage/Storage/Internal/File/Controller/AWSS3FileController.cs +++ b/Storage/Storage/Internal/File/Controller/AWSS3FileController.cs @@ -6,28 +6,14 @@ using LeanCloud.Storage.Internal; using System.Collections.Generic; using System.Net.Http; -namespace LeanCloud.Storage.Internal -{ - internal class AWSS3FileController : AVFileController - { - - private object mutex = new object(); - - - public AWSS3FileController(IAVCommandRunner commandRunner) : base(commandRunner) - { - - } - - public override Task SaveAsync(FileState state, Stream dataStream, string sessionToken, IProgress progress, CancellationToken cancellationToken = default(System.Threading.CancellationToken)) - { - if (state.Url != null) - { +namespace LeanCloud.Storage.Internal { + internal class AWSS3FileController : AVFileController { + public override Task SaveAsync(FileState state, Stream dataStream, string sessionToken, IProgress progress, CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { + if (state.Url != null) { return Task.FromResult(state); } - return GetFileToken(state, cancellationToken).OnSuccess(t => - { + return GetFileToken(state, cancellationToken).OnSuccess(t => { var fileToken = t.Result.Item2; var uploadUrl = fileToken["upload_url"].ToString(); state.ObjectId = fileToken["objectId"].ToString(); @@ -35,14 +21,12 @@ namespace LeanCloud.Storage.Internal state.Url = new Uri(url, UriKind.Absolute); return PutFile(state, uploadUrl, dataStream); - }).Unwrap().OnSuccess(s => - { + }).Unwrap().OnSuccess(s => { return s.Result; }); } - internal async Task PutFile(FileState state, string uploadUrl, Stream dataStream) - { + internal async Task PutFile(FileState state, string uploadUrl, Stream dataStream) { IList> makeBlockHeaders = new List>(); makeBlockHeaders.Add(new KeyValuePair("Content-Type", state.MimeType)); var request = new HttpRequest { diff --git a/Storage/Storage/Internal/File/Controller/IAVFileController.cs b/Storage/Storage/Internal/File/Controller/IAVFileController.cs deleted file mode 100644 index 2dea784..0000000 --- a/Storage/Storage/Internal/File/Controller/IAVFileController.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal -{ - public interface IAVFileController - { - Task SaveAsync(FileState state, - Stream dataStream, - String sessionToken, - IProgress progress, - CancellationToken cancellationToken); - - Task DeleteAsync(FileState state, - string sessionToken, - CancellationToken cancellationToken); - - Task GetAsync(string objectId, - string sessionToken, - CancellationToken cancellationToken); - } -} diff --git a/Storage/Storage/Internal/File/Controller/QCloudCosFileController.cs b/Storage/Storage/Internal/File/Controller/QCloudCosFileController.cs index 053a16b..30b4037 100644 --- a/Storage/Storage/Internal/File/Controller/QCloudCosFileController.cs +++ b/Storage/Storage/Internal/File/Controller/QCloudCosFileController.cs @@ -8,10 +8,8 @@ using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; -namespace LeanCloud.Storage.Internal -{ - internal class QCloudCosFileController : AVFileController - { +namespace LeanCloud.Storage.Internal { + internal class QCloudCosFileController : AVFileController { private object mutex = new object(); FileState fileState; @@ -22,32 +20,24 @@ namespace LeanCloud.Storage.Internal bool done; private long sliceSize = (long)CommonSize.KB512; - public QCloudCosFileController(IAVCommandRunner commandRunner) : base(commandRunner) - { - } - public Task SaveAsync(FileState state, Stream dataStream, string sessionToken, IProgress progress, - CancellationToken cancellationToken) - { - if (state.Url != null) - { + CancellationToken cancellationToken) { + if (state.Url != null) { return Task.FromResult(state); } fileState = state; data = dataStream; - return GetFileToken(fileState, cancellationToken).OnSuccess(_ => - { + return GetFileToken(fileState, cancellationToken).OnSuccess(_ => { var fileToken = _.Result.Item2; uploadUrl = fileToken["upload_url"].ToString(); token = fileToken["token"].ToString(); fileState.ObjectId = fileToken["objectId"].ToString(); bucket = fileToken["bucket"].ToString(); - return FileSlice(cancellationToken).OnSuccess(t => - { + return FileSlice(cancellationToken).OnSuccess(t => { if (done) return Task.FromResult(state); var response = t.Result.Item2; var resumeData = response["data"] as IDictionary; @@ -65,32 +55,25 @@ namespace LeanCloud.Storage.Internal long offset, Stream dataStream, IProgress progress, - CancellationToken cancellationToken) - { + CancellationToken cancellationToken) { long dataLength = dataStream.Length; - if (progress != null) - { - lock (mutex) - { - progress.Report(new AVUploadProgressEventArgs() - { + if (progress != null) { + lock (mutex) { + progress.Report(new AVUploadProgressEventArgs() { Progress = AVFileController.CalcProgress(offset, dataLength) }); } } - if (offset == dataLength) - { + if (offset == dataLength) { return Task.FromResult(fileState); } var sliceFile = GetNextBinary(offset, dataStream); - return ExcuteUpload(sessionId, offset, sliceFile, cancellationToken).OnSuccess(_ => - { + return ExcuteUpload(sessionId, offset, sliceFile, cancellationToken).OnSuccess(_ => { offset += sliceFile.Length; - if (offset == dataLength) - { + if (offset == dataLength) { done = true; return Task.FromResult(fileState); } @@ -101,8 +84,7 @@ namespace LeanCloud.Storage.Internal }).Unwrap(); } - Task>> ExcuteUpload(string sessionId, long offset, byte[] sliceFile, CancellationToken cancellationToken) - { + Task>> ExcuteUpload(string sessionId, long offset, byte[] sliceFile, CancellationToken cancellationToken) { var body = new Dictionary(); body.Add("op", "upload_slice"); body.Add("session", sessionId); @@ -111,26 +93,20 @@ namespace LeanCloud.Storage.Internal return PostToQCloud(body, sliceFile, cancellationToken); } - Task>> FileSlice(CancellationToken cancellationToken) - { + Task>> FileSlice(CancellationToken cancellationToken) { SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); var body = new Dictionary(); - if (data.Length <= (long)CommonSize.KB512) - { + if (data.Length <= (long)CommonSize.KB512) { body.Add("op", "upload"); body.Add("sha", HexStringFromBytes(sha1.ComputeHash(data))); var wholeFile = GetNextBinary(0, data); - return PostToQCloud(body, wholeFile, cancellationToken).OnSuccess(_ => - { - if (_.Result.Item1 == HttpStatusCode.OK) - { + return PostToQCloud(body, wholeFile, cancellationToken).OnSuccess(_ => { + if (_.Result.Item1 == HttpStatusCode.OK) { done = true; } return _.Result; }); - } - else - { + } else { body.Add("op", "upload_slice"); body.Add("filesize", data.Length); body.Add("sha", HexStringFromBytes(sha1.ComputeHash(data))); @@ -139,19 +115,16 @@ namespace LeanCloud.Storage.Internal return PostToQCloud(body, null, cancellationToken); } - public static string HexStringFromBytes(byte[] bytes) - { + public static string HexStringFromBytes(byte[] bytes) { var sb = new StringBuilder(); - foreach (byte b in bytes) - { + foreach (byte b in bytes) { var hex = b.ToString("x2"); sb.Append(hex); } return sb.ToString(); } - public static string SHA1HashStringForUTF8String(string s) - { + public static string SHA1HashStringForUTF8String(string s) { byte[] bytes = Encoding.UTF8.GetBytes(s); SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); @@ -162,8 +135,7 @@ namespace LeanCloud.Storage.Internal async Task>> PostToQCloud( Dictionary body, byte[] sliceFile, - CancellationToken cancellationToken) - { + CancellationToken cancellationToken) { IList> sliceHeaders = new List>(); sliceHeaders.Add(new KeyValuePair("Authorization", this.token)); @@ -185,8 +157,7 @@ namespace LeanCloud.Storage.Internal JsonConvert.DeserializeObject>(ret.Item2, new LeanCloudJsonConverter())); return result; } - public static Stream HttpUploadFile(byte[] file, string fileName, out string contentType, out long contentLength, IDictionary nvc) - { + public static Stream HttpUploadFile(byte[] file, string fileName, out string contentType, out long contentLength, IDictionary nvc) { string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); byte[] boundarybytes = StringToAscii("\r\n--" + boundary + "\r\n"); contentType = "multipart/form-data; boundary=" + boundary; @@ -194,8 +165,7 @@ namespace LeanCloud.Storage.Internal MemoryStream rs = new MemoryStream(); string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; - foreach (string key in nvc.Keys) - { + foreach (string key in nvc.Keys) { rs.Write(boundarybytes, 0, boundarybytes.Length); string formitem = string.Format(formdataTemplate, key, nvc[key]); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); @@ -203,8 +173,7 @@ namespace LeanCloud.Storage.Internal } rs.Write(boundarybytes, 0, boundarybytes.Length); - if (file != null) - { + if (file != null) { string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n"; string header = string.Format(headerTemplate, "fileContent", fileName, "application/octet-stream"); byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); @@ -224,11 +193,9 @@ namespace LeanCloud.Storage.Internal return new MemoryStream(tempBuffer); } - public static byte[] StringToAscii(string s) - { + public static byte[] StringToAscii(string s) { byte[] retval = new byte[s.Length]; - for (int ix = 0; ix < s.Length; ++ix) - { + for (int ix = 0; ix < s.Length; ++ix) { char ch = s[ix]; if (ch <= 0x7f) retval[ix] = (byte)ch; else retval[ix] = (byte)'?'; @@ -236,10 +203,8 @@ namespace LeanCloud.Storage.Internal return retval; } - byte[] GetNextBinary(long completed, Stream dataStream) - { - if (completed + sliceSize > dataStream.Length) - { + byte[] GetNextBinary(long completed, Stream dataStream) { + if (completed + sliceSize > dataStream.Length) { sliceSize = dataStream.Length - completed; } diff --git a/Storage/Storage/Internal/File/Controller/QiniuFileController.cs b/Storage/Storage/Internal/File/Controller/QiniuFileController.cs index c1de447..5dd8269 100644 --- a/Storage/Storage/Internal/File/Controller/QiniuFileController.cs +++ b/Storage/Storage/Internal/File/Controller/QiniuFileController.cs @@ -31,11 +31,6 @@ namespace LeanCloud.Storage.Internal internal static string UP_HOST = "https://up.qbox.me"; private object mutex = new object(); - public QiniuFileController(IAVCommandRunner commandRunner) : base(commandRunner) - { - - } - public override Task SaveAsync(FileState state, Stream dataStream, String sessionToken, @@ -165,7 +160,7 @@ namespace LeanCloud.Storage.Internal Method = HttpMethod.Post, Content = parameters }; - return commandRunner.RunCommandAsync>(command); + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command); } IList> GetQiniuRequestHeaders(FileState state) { diff --git a/Storage/Storage/Internal/HttpClient/HttpClient.cs b/Storage/Storage/Internal/HttpClient/HttpClient.cs index b0aa0c7..ee941b9 100644 --- a/Storage/Storage/Internal/HttpClient/HttpClient.cs +++ b/Storage/Storage/Internal/HttpClient/HttpClient.cs @@ -10,7 +10,7 @@ using System.IO; using NetHttpClient = System.Net.Http.HttpClient; namespace LeanCloud.Storage.Internal { - public class HttpClient : IHttpClient { + public class HttpClient { static readonly HashSet HttpContentHeaders = new HashSet { { "Allow" }, { "Content-Disposition" }, @@ -41,7 +41,7 @@ namespace LeanCloud.Storage.Internal { IProgress uploadProgress, IProgress downloadProgress, CancellationToken cancellationToken) { - + HttpMethod httpMethod = httpRequest.Method; HttpRequestMessage message = new HttpRequestMessage(httpMethod, httpRequest.Uri); diff --git a/Storage/Storage/Internal/HttpClient/IHttpClient.cs b/Storage/Storage/Internal/HttpClient/IHttpClient.cs deleted file mode 100644 index 6bbe9d2..0000000 --- a/Storage/Storage/Internal/HttpClient/IHttpClient.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Net; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal -{ - public interface IHttpClient - { - /// - /// Executes HTTP request to a with HTTP verb - /// and . - /// - /// The HTTP request to be executed. - /// Upload progress callback. - /// Download progress callback. - /// The cancellation token. - /// A task that resolves to Htt - Task> ExecuteAsync(HttpRequest httpRequest, - IProgress uploadProgress, - IProgress downloadProgress, - CancellationToken cancellationToken); - } -} diff --git a/Storage/Storage/Internal/IAVCorePlugins.cs b/Storage/Storage/Internal/IAVCorePlugins.cs deleted file mode 100644 index 51060bd..0000000 --- a/Storage/Storage/Internal/IAVCorePlugins.cs +++ /dev/null @@ -1,26 +0,0 @@ -using LeanCloud.Storage.Internal; -using System; - -namespace LeanCloud.Storage.Internal -{ - public interface IAVCorePlugins - { - void Reset(); - - IHttpClient HttpClient { get; } - IAppRouterController AppRouterController { get; } - IAVCommandRunner CommandRunner { get; } - IStorageController StorageController { get; } - - IAVCloudCodeController CloudCodeController { get; } - IAVConfigController ConfigController { get; } - IAVFileController FileController { get; } - IAVObjectController ObjectController { get; } - IAVQueryController QueryController { get; } - IAVSessionController SessionController { get; } - IAVUserController UserController { get; } - IObjectSubclassingController SubclassingController { get; } - IAVCurrentUserController CurrentUserController { get; } - IInstallationIdController InstallationIdController { get; } - } -} \ No newline at end of file diff --git a/Storage/Storage/Internal/InstallationId/Controller/IInstallationIdController.cs b/Storage/Storage/Internal/InstallationId/Controller/IInstallationIdController.cs deleted file mode 100644 index 1fb9af4..0000000 --- a/Storage/Storage/Internal/InstallationId/Controller/IInstallationIdController.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal { - public interface IInstallationIdController { - /// - /// Sets current installationId and saves it to local storage. - /// - /// The installationId to be saved. - Task SetAsync(Guid? installationId); - - /// - /// Gets current installationId from local storage. Generates a none exists. - /// - /// Current installationId. - Task GetAsync(); - - /// - /// Clears current installationId from memory and local storage. - /// - Task ClearAsync(); - } -} diff --git a/Storage/Storage/Internal/InstallationId/Controller/InstallationIdController.cs b/Storage/Storage/Internal/InstallationId/Controller/InstallationIdController.cs index d28b015..ceb22e7 100644 --- a/Storage/Storage/Internal/InstallationId/Controller/InstallationIdController.cs +++ b/Storage/Storage/Internal/InstallationId/Controller/InstallationIdController.cs @@ -1,66 +1,59 @@ -using LeanCloud.Storage.Internal; -using System; -using System.Threading; +using System; 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; + public class InstallationIdController { + 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 { + public Task SetAsync(Guid? installationId) { lock (mutex) { - installationId = new Guid((string)id); - return Task.FromResult(installationId); - } - } catch (Exception) { - var newInstallationId = Guid.NewGuid(); - return SetAsync(newInstallationId).OnSuccess(_ => newInstallationId); - } - }) - .Unwrap(); - } + Task saveTask; - public Task ClearAsync() { - return SetAsync(null); + if (installationId == null) { + saveTask = AVPlugins.Instance.StorageController + .LoadAsync() + .OnSuccess(storage => storage.Result.RemoveAsync(InstallationIdKey)) + .Unwrap(); + } else { + saveTask = AVPlugins.Instance.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 AVPlugins.Instance.StorageController + .LoadAsync() + .OnSuccess(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); + } } - } } diff --git a/Storage/Storage/Internal/Object/Controller/AVObjectController.cs b/Storage/Storage/Internal/Object/Controller/AVObjectController.cs index f48f9ae..9493344 100644 --- a/Storage/Storage/Internal/Object/Controller/AVObjectController.cs +++ b/Storage/Storage/Internal/Object/Controller/AVObjectController.cs @@ -7,13 +7,7 @@ using LeanCloud.Utilities; using System.Net.Http; namespace LeanCloud.Storage.Internal { - public class AVObjectController : IAVObjectController { - private readonly IAVCommandRunner commandRunner; - - public AVObjectController(IAVCommandRunner commandRunner) { - this.commandRunner = commandRunner; - } - + public class AVObjectController { public Task FetchAsync(IObjectState state, string sessionToken, CancellationToken cancellationToken) { @@ -21,7 +15,7 @@ namespace LeanCloud.Storage.Internal { Path = $"classes/{Uri.EscapeDataString(state.ClassName)}/{Uri.EscapeDataString(state.ObjectId)}", Method = HttpMethod.Get }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance); }); } @@ -34,7 +28,7 @@ namespace LeanCloud.Storage.Internal { Path = $"classes/{Uri.EscapeDataString(state.ClassName)}/{Uri.EscapeDataString(state.ObjectId)}?{AVClient.BuildQueryString(queryString)}", Method = HttpMethod.Get }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance); }); } @@ -49,7 +43,7 @@ namespace LeanCloud.Storage.Internal { Method = state.ObjectId == null ? HttpMethod.Post : HttpMethod.Put, Content = objectJSON }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance); serverState = serverState.MutatedClone(mutableClone => { mutableClone.IsNew = t.Result.Item1 == System.Net.HttpStatusCode.Created; @@ -62,7 +56,7 @@ namespace LeanCloud.Storage.Internal { IList> operationsList, string sessionToken, CancellationToken cancellationToken) { - + var requests = states .Zip(operationsList, (item, ops) => new AVCommand { Path = item.ObjectId == null ? $"classes/{Uri.EscapeDataString(item.ClassName)}" : $"classes/{Uri.EscapeDataString(item.ClassName)}/{Uri.EscapeDataString(item.ObjectId)}", @@ -89,7 +83,7 @@ namespace LeanCloud.Storage.Internal { Path = $"classes/{state.ClassName}/{state.ObjectId}", Method = HttpMethod.Delete }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken); + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken); } public IList DeleteAllAsync(IList states, @@ -157,7 +151,7 @@ namespace LeanCloud.Storage.Internal { { "requests", encodedRequests } } }; - commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).ContinueWith(t => { + AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).ContinueWith(t => { if (t.IsFaulted || t.IsCanceled) { foreach (var tcs in tcss) { if (t.IsFaulted) { diff --git a/Storage/Storage/Internal/Object/Controller/IAVObjectController.cs b/Storage/Storage/Internal/Object/Controller/IAVObjectController.cs deleted file mode 100644 index 9230eb5..0000000 --- a/Storage/Storage/Internal/Object/Controller/IAVObjectController.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal -{ - public interface IAVObjectController - { - //Task FetchAsync(IObjectState state, - // string sessionToken, - // CancellationToken cancellationToken); - - Task FetchAsync(IObjectState state, - IDictionary queryString, - string sessionToken, - CancellationToken cancellationToken); - - Task SaveAsync(IObjectState state, - IDictionary operations, - string sessionToken, - CancellationToken cancellationToken); - - IList> SaveAllAsync(IList states, - IList> operationsList, - string sessionToken, - CancellationToken cancellationToken); - - Task DeleteAsync(IObjectState state, - string sessionToken, - CancellationToken cancellationToken); - - IList DeleteAllAsync(IList states, - string sessionToken, - CancellationToken cancellationToken); - } -} diff --git a/Storage/Storage/Internal/Object/Subclassing/IObjectSubclassingController.cs b/Storage/Storage/Internal/Object/Subclassing/IObjectSubclassingController.cs deleted file mode 100644 index 38322fc..0000000 --- a/Storage/Storage/Internal/Object/Subclassing/IObjectSubclassingController.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal -{ - public interface IObjectSubclassingController - { - String GetClassName(Type type); - Type GetType(String className); - - bool IsTypeValid(String className, Type type); - - void RegisterSubclass(Type t); - void UnregisterSubclass(Type t); - - void AddRegisterHook(Type t, Action action); - - AVObject Instantiate(String className); - IDictionary GetPropertyMappings(String className); - } -} diff --git a/Storage/Storage/Internal/Object/Subclassing/ObjectSubclassingController.cs b/Storage/Storage/Internal/Object/Subclassing/ObjectSubclassingController.cs index b1f913e..442e246 100644 --- a/Storage/Storage/Internal/Object/Subclassing/ObjectSubclassingController.cs +++ b/Storage/Storage/Internal/Object/Subclassing/ObjectSubclassingController.cs @@ -1,24 +1,19 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; using System.Threading; -using LeanCloud.Storage.Internal; -namespace LeanCloud.Storage.Internal -{ - internal class ObjectSubclassingController : IObjectSubclassingController - { +namespace LeanCloud.Storage.Internal { + public class ObjectSubclassingController { // Class names starting with _ are documented to be reserved. Use this one // here to allow us to 'inherit' certain properties. private static readonly string avObjectClassName = "_AVObject"; private readonly ReaderWriterLockSlim mutex; - private readonly IDictionary registeredSubclasses; - private Dictionary registerActions; + private readonly IDictionary registeredSubclasses; + private Dictionary registerActions; - public ObjectSubclassingController() - { + public ObjectSubclassingController() { mutex = new ReaderWriterLockSlim(); registeredSubclasses = new Dictionary(); registerActions = new Dictionary(); @@ -28,15 +23,13 @@ namespace LeanCloud.Storage.Internal RegisterSubclass(typeof(AVObject)); } - public String GetClassName(Type type) - { + public string GetClassName(Type type) { return type == typeof(AVObject) ? avObjectClassName : ObjectSubclassInfo.GetClassName(type.GetTypeInfo()); } - public Type GetType(String className) - { + public Type GetType(string className) { ObjectSubclassInfo info = null; mutex.EnterReadLock(); registeredSubclasses.TryGetValue(className, out info); @@ -47,8 +40,7 @@ namespace LeanCloud.Storage.Internal : null; } - public bool IsTypeValid(String className, Type type) - { + public bool IsTypeValid(string className, Type type) { ObjectSubclassInfo subclassInfo = null; mutex.EnterReadLock(); @@ -60,39 +52,30 @@ namespace LeanCloud.Storage.Internal : subclassInfo.TypeInfo == type.GetTypeInfo(); } - public void RegisterSubclass(Type type) - { + public void RegisterSubclass(Type type) { TypeInfo typeInfo = type.GetTypeInfo(); - if (!typeof(AVObject).GetTypeInfo().IsAssignableFrom(typeInfo)) - { + if (!typeof(AVObject).GetTypeInfo().IsAssignableFrom(typeInfo)) { throw new ArgumentException("Cannot register a type that is not a subclass of AVObject"); } - String className = GetClassName(type); + string className = GetClassName(type); - try - { + try { // Perform this as a single independent transaction, so we can never get into an // intermediate state where we *theoretically* register the wrong class due to a // TOCTTOU bug. mutex.EnterWriteLock(); ObjectSubclassInfo previousInfo = null; - if (registeredSubclasses.TryGetValue(className, out previousInfo)) - { - if (typeInfo.IsAssignableFrom(previousInfo.TypeInfo)) - { + if (registeredSubclasses.TryGetValue(className, out previousInfo)) { + if (typeInfo.IsAssignableFrom(previousInfo.TypeInfo)) { // Previous subclass is more specific or equal to the current type, do nothing. return; - } - else if (previousInfo.TypeInfo.IsAssignableFrom(typeInfo)) - { + } else if (previousInfo.TypeInfo.IsAssignableFrom(typeInfo)) { // Previous subclass is parent of new child, fallthrough and actually register // this class. /* Do nothing */ - } - else - { + } else { throw new ArgumentException( "Tried to register both " + previousInfo.TypeInfo.FullName + " and " + typeInfo.FullName + " as the AVObject subclass of " + className + ". Cannot determine the right class " + @@ -102,15 +85,12 @@ namespace LeanCloud.Storage.Internal } ConstructorInfo constructor = type.FindConstructor(); - if (constructor == null) - { + if (constructor == null) { throw new ArgumentException("Cannot register a type that does not implement the default constructor!"); } registeredSubclasses[className] = new ObjectSubclassInfo(type, constructor); - } - finally - { + } finally { mutex.ExitWriteLock(); } @@ -120,28 +100,24 @@ namespace LeanCloud.Storage.Internal registerActions.TryGetValue(className, out toPerform); mutex.ExitReadLock(); - if (toPerform != null) - { + if (toPerform != null) { toPerform(); } } - public void UnregisterSubclass(Type type) - { + public void UnregisterSubclass(Type type) { mutex.EnterWriteLock(); registeredSubclasses.Remove(GetClassName(type)); mutex.ExitWriteLock(); } - public void AddRegisterHook(Type t, Action action) - { + public void AddRegisterHook(Type t, Action action) { mutex.EnterWriteLock(); registerActions.Add(GetClassName(t), action); mutex.ExitWriteLock(); } - public AVObject Instantiate(String className) - { + public AVObject Instantiate(String className) { ObjectSubclassInfo info = null; mutex.EnterReadLock(); @@ -153,13 +129,11 @@ namespace LeanCloud.Storage.Internal : new AVObject(className); } - public IDictionary GetPropertyMappings(String className) - { + public IDictionary GetPropertyMappings(String className) { ObjectSubclassInfo info = null; mutex.EnterReadLock(); registeredSubclasses.TryGetValue(className, out info); - if (info == null) - { + if (info == null) { registeredSubclasses.TryGetValue(avObjectClassName, out info); } mutex.ExitReadLock(); diff --git a/Storage/Storage/Internal/Query/Controller/AVQueryController.cs b/Storage/Storage/Internal/Query/Controller/AVQueryController.cs index d53c361..c9289e5 100644 --- a/Storage/Storage/Internal/Query/Controller/AVQueryController.cs +++ b/Storage/Storage/Internal/Query/Controller/AVQueryController.cs @@ -5,25 +5,13 @@ using System.Net.Http; using System.Threading; using System.Threading.Tasks; -namespace LeanCloud.Storage.Internal -{ - internal class AVQueryController : IAVQueryController - { - private readonly IAVCommandRunner commandRunner; - - public AVQueryController(IAVCommandRunner commandRunner) - { - this.commandRunner = commandRunner; - } - - public Task> FindAsync(AVQuery query, - AVUser user, - CancellationToken cancellationToken) where T : AVObject - { +namespace LeanCloud.Storage.Internal { + public class AVQueryController { + public Task> FindAsync(AVQuery query, AVUser user, + CancellationToken cancellationToken) where T : AVObject { string sessionToken = user != null ? user.SessionToken : null; - return FindAsync(query.Path, query.BuildParameters(), sessionToken, cancellationToken).OnSuccess(t => - { + return FindAsync(query.Path, query.BuildParameters(), sessionToken, cancellationToken).OnSuccess(t => { var items = t.Result["results"] as IList; return (from item in items @@ -33,35 +21,30 @@ namespace LeanCloud.Storage.Internal public Task CountAsync(AVQuery query, AVUser user, - CancellationToken cancellationToken) where T : AVObject - { + CancellationToken cancellationToken) where T : AVObject { string sessionToken = user != null ? user.SessionToken : null; var parameters = query.BuildParameters(); parameters["limit"] = 0; parameters["count"] = 1; - return FindAsync(query.Path, parameters, sessionToken, cancellationToken).OnSuccess(t => - { + return FindAsync(query.Path, parameters, sessionToken, cancellationToken).OnSuccess(t => { return Convert.ToInt32(t.Result["count"]); }); } public Task FirstAsync(AVQuery query, AVUser user, - CancellationToken cancellationToken) where T : AVObject - { + CancellationToken cancellationToken) where T : AVObject { string sessionToken = user?.SessionToken; var parameters = query.BuildParameters(); parameters["limit"] = 1; - return FindAsync(query.Path, parameters, sessionToken, cancellationToken).OnSuccess(t => - { + return FindAsync(query.Path, parameters, sessionToken, cancellationToken).OnSuccess(t => { var items = t.Result["results"] as IList; var item = items.FirstOrDefault() as IDictionary; // Not found. Return empty state. - if (item == null) - { + if (item == null) { return (IObjectState)null; } @@ -72,34 +55,14 @@ namespace LeanCloud.Storage.Internal private Task> FindAsync(string path, IDictionary parameters, string sessionToken, - CancellationToken cancellationToken) - { + CancellationToken cancellationToken) { var command = new AVCommand { Path = $"{path}?{AVClient.BuildQueryString(parameters)}", Method = HttpMethod.Get }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => - { + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { return t.Result.Item2; }); } - - //private Task> FindAsync(string className, - // IDictionary parameters, - // string sessionToken, - // CancellationToken cancellationToken) - //{ - // var command = new AVCommand(string.Format("classes/{0}?{1}", - // Uri.EscapeDataString(className), - // AVClient.BuildQueryString(parameters)), - // method: "GET", - // sessionToken: sessionToken, - // data: null); - - // return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => - // { - // return t.Result.Item2; - // }); - //} } } diff --git a/Storage/Storage/Internal/Query/Controller/IAVQueryController.cs b/Storage/Storage/Internal/Query/Controller/IAVQueryController.cs deleted file mode 100644 index f5d1494..0000000 --- a/Storage/Storage/Internal/Query/Controller/IAVQueryController.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal { - public interface IAVQueryController { - Task> FindAsync(AVQuery query, - AVUser user, - CancellationToken cancellationToken) where T : AVObject; - - Task CountAsync(AVQuery query, - AVUser user, - CancellationToken cancellationToken) where T : AVObject; - - Task FirstAsync(AVQuery query, - AVUser user, - CancellationToken cancellationToken) where T : AVObject; - } -} diff --git a/Storage/Storage/Internal/Session/Controller/AVSessionController.cs b/Storage/Storage/Internal/Session/Controller/AVSessionController.cs index cff5d49..60957f0 100644 --- a/Storage/Storage/Internal/Session/Controller/AVSessionController.cs +++ b/Storage/Storage/Internal/Session/Controller/AVSessionController.cs @@ -5,19 +5,13 @@ using System.Threading.Tasks; using System.Net.Http; namespace LeanCloud.Storage.Internal { - public class AVSessionController : IAVSessionController { - private readonly IAVCommandRunner commandRunner; - - public AVSessionController(IAVCommandRunner commandRunner) { - this.commandRunner = commandRunner; - } - + public class AVSessionController { public Task GetSessionAsync(string sessionToken, CancellationToken cancellationToken) { var command = new AVCommand { Path = "sessions/me", Method = HttpMethod.Get }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance); }); } @@ -27,7 +21,7 @@ namespace LeanCloud.Storage.Internal { Path = "logout", Method = HttpMethod.Post }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken); + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken); } public Task UpgradeToRevocableSessionAsync(string sessionToken, CancellationToken cancellationToken) { @@ -35,7 +29,7 @@ namespace LeanCloud.Storage.Internal { Path = "upgradeToRevocableSession", Method = HttpMethod.Post, }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance); }); } diff --git a/Storage/Storage/Internal/Session/Controller/IAVSessionController.cs b/Storage/Storage/Internal/Session/Controller/IAVSessionController.cs deleted file mode 100644 index 72e7e95..0000000 --- a/Storage/Storage/Internal/Session/Controller/IAVSessionController.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal { - public interface IAVSessionController { - Task GetSessionAsync(string sessionToken, CancellationToken cancellationToken); - - Task RevokeAsync(string sessionToken, CancellationToken cancellationToken); - - Task UpgradeToRevocableSessionAsync(string sessionToken, CancellationToken cancellationToken); - - bool IsRevocableSessionToken(string sessionToken); - } -} diff --git a/Storage/Storage/Internal/Storage/IStorageController.cs b/Storage/Storage/Internal/Storage/IStorageController.cs deleted file mode 100644 index b334c92..0000000 --- a/Storage/Storage/Internal/Storage/IStorageController.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal { - /// - /// An abstraction for accessing persistent storage in the LeanCloud SDK. - /// - public interface IStorageController { - /// - /// Load the contents of this storage controller asynchronously. - /// - /// - Task> LoadAsync(); - - /// - /// Overwrites the contents of this storage controller asynchronously. - /// - /// - /// - Task> SaveAsync(IDictionary contents); - } - - /// - /// An interface for a dictionary that is persisted to disk asynchronously. - /// - /// They key type of the dictionary. - /// The value type of the dictionary. - public interface IStorageDictionary : IEnumerable> { - int Count { get; } - TValue this[TKey key] { get; } - - IEnumerable Keys { get; } - IEnumerable Values { get; } - - bool ContainsKey(TKey key); - bool TryGetValue(TKey key, out TValue value); - - /// - /// Adds a key to this dictionary, and saves it asynchronously. - /// - /// The key to insert. - /// The value to insert. - /// - Task AddAsync(TKey key, TValue value); - - /// - /// Removes a key from this dictionary, and saves it asynchronously. - /// - /// - /// - Task RemoveAsync(TKey key); - } -} \ No newline at end of file diff --git a/Storage/Storage/Internal/Storage/Portable/StorageController.cs b/Storage/Storage/Internal/Storage/StorageController.cs similarity index 72% rename from Storage/Storage/Internal/Storage/Portable/StorageController.cs rename to Storage/Storage/Internal/Storage/StorageController.cs index d12bc07..b5dcb27 100644 --- a/Storage/Storage/Internal/Storage/Portable/StorageController.cs +++ b/Storage/Storage/Internal/Storage/StorageController.cs @@ -6,28 +6,23 @@ using System.Collections.Generic; using System.Threading; using Newtonsoft.Json; -namespace LeanCloud.Storage.Internal -{ +namespace LeanCloud.Storage.Internal { /// /// Implements `IStorageController` for PCL targets, based off of PCLStorage. /// - public class StorageController : IStorageController - { - private class StorageDictionary : IStorageDictionary - { + public class StorageController { + public class StorageDictionary : IEnumerable> { private readonly string filePath; - private Dictionary dictionary; + private Dictionary dictionary; readonly ReaderWriterLockSlim locker = new ReaderWriterLockSlim(); - public StorageDictionary(string filePath) - { + public StorageDictionary(string filePath) { this.filePath = filePath; dictionary = new Dictionary(); } - internal Task SaveAsync() - { + internal Task SaveAsync() { string json; locker.EnterReadLock(); json = JsonConvert.SerializeObject(dictionary); @@ -37,8 +32,7 @@ namespace LeanCloud.Storage.Internal } } - internal async Task LoadAsync() - { + internal async Task LoadAsync() { using (var sr = new StreamReader(filePath)) { var text = await sr.ReadToEndAsync(); Dictionary result = null; @@ -54,31 +48,27 @@ namespace LeanCloud.Storage.Internal } } - internal void Update(IDictionary contents) - { + internal void Update(IDictionary contents) { locker.EnterWriteLock(); dictionary = contents.ToDictionary(p => p.Key, p => p.Value); locker.ExitWriteLock(); } - public Task AddAsync(string key, object value) - { + public Task AddAsync(string key, object value) { locker.EnterWriteLock(); dictionary[key] = value; locker.ExitWriteLock(); return SaveAsync(); } - public Task RemoveAsync(string key) - { + public Task RemoveAsync(string key) { locker.EnterWriteLock(); dictionary.Remove(key); locker.ExitWriteLock(); return SaveAsync(); } - public bool ContainsKey(string key) - { + public bool ContainsKey(string key) { try { locker.EnterReadLock(); return dictionary.ContainsKey(key); @@ -87,8 +77,7 @@ namespace LeanCloud.Storage.Internal } } - public IEnumerable Keys - { + public IEnumerable Keys { get { try { locker.EnterReadLock(); @@ -99,8 +88,7 @@ namespace LeanCloud.Storage.Internal } } - public bool TryGetValue(string key, out object value) - { + public bool TryGetValue(string key, out object value) { try { locker.EnterReadLock(); return dictionary.TryGetValue(key, out value); @@ -109,8 +97,7 @@ namespace LeanCloud.Storage.Internal } } - public IEnumerable Values - { + public IEnumerable Values { get { try { locker.EnterReadLock(); @@ -121,8 +108,7 @@ namespace LeanCloud.Storage.Internal } } - public object this[string key] - { + public object this[string key] { get { try { locker.EnterReadLock(); @@ -133,8 +119,7 @@ namespace LeanCloud.Storage.Internal } } - public int Count - { + public int Count { get { try { locker.EnterReadLock(); @@ -145,8 +130,7 @@ namespace LeanCloud.Storage.Internal } } - public IEnumerator> GetEnumerator() - { + public IEnumerator> GetEnumerator() { try { locker.EnterReadLock(); return dictionary.GetEnumerator(); @@ -155,8 +139,7 @@ namespace LeanCloud.Storage.Internal } } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { try { locker.EnterReadLock(); return dictionary.GetEnumerator(); @@ -171,46 +154,38 @@ namespace LeanCloud.Storage.Internal private readonly Task fileTask; private StorageDictionary storageDictionary; - public StorageController(string fileNamePrefix) - { - fileTask = taskQueue.Enqueue(t => t.ContinueWith(_ => - { + public StorageController(string fileNamePrefix) { + fileTask = taskQueue.Enqueue(t => t.ContinueWith(_ => { string path = $"{fileNamePrefix}_{LeanCloudStorageFileName}"; File.CreateText(path); return path; }), CancellationToken.None); } - public Task> LoadAsync() - { - return taskQueue.Enqueue(toAwait => - { - return toAwait.ContinueWith(_ => - { - if (storageDictionary != null) - { - return Task.FromResult>(storageDictionary); + public Task LoadAsync() { + return taskQueue.Enqueue(toAwait => { + return toAwait.ContinueWith(_ => { + if (storageDictionary != null) { + return Task.FromResult(storageDictionary); } storageDictionary = new StorageDictionary(fileTask.Result); - return storageDictionary.LoadAsync().OnSuccess(__ => storageDictionary as IStorageDictionary); + return storageDictionary.LoadAsync() + .OnSuccess(__ => storageDictionary); }).Unwrap(); }, CancellationToken.None); } - public Task> SaveAsync(IDictionary contents) - { - return taskQueue.Enqueue(toAwait => - { - return toAwait.ContinueWith(_ => - { - if (storageDictionary == null) - { + public Task SaveAsync(IDictionary contents) { + return taskQueue.Enqueue(toAwait => { + return toAwait.ContinueWith(_ => { + if (storageDictionary == null) { storageDictionary = new StorageDictionary(fileTask.Result); } storageDictionary.Update(contents); - return storageDictionary.SaveAsync().OnSuccess(__ => storageDictionary as IStorageDictionary); + return storageDictionary.SaveAsync() + .OnSuccess(__ => storageDictionary); }).Unwrap(); }, CancellationToken.None); } diff --git a/Storage/Storage/Internal/User/Controller/AVCurrentUserController.cs b/Storage/Storage/Internal/User/Controller/AVCurrentUserController.cs index 93e3b22..ad80193 100644 --- a/Storage/Storage/Internal/User/Controller/AVCurrentUserController.cs +++ b/Storage/Storage/Internal/User/Controller/AVCurrentUserController.cs @@ -9,17 +9,9 @@ using Newtonsoft.Json; namespace LeanCloud.Storage.Internal { - public class AVCurrentUserController : IAVCurrentUserController + public class AVCurrentUserController { private readonly object mutex = new object(); - private readonly TaskQueue taskQueue = new TaskQueue(); - - private IStorageController storageController; - - public AVCurrentUserController(IStorageController storageController) - { - this.storageController = storageController; - } private AVUser currentUser; public AVUser CurrentUser @@ -45,7 +37,7 @@ namespace LeanCloud.Storage.Internal Task saveTask = null; if (user == null) { - saveTask = storageController + saveTask = AVPlugins.Instance.StorageController .LoadAsync() .OnSuccess(t => t.Result.RemoveAsync("CurrentUser")) .Unwrap(); @@ -65,7 +57,7 @@ namespace LeanCloud.Storage.Internal CultureInfo.InvariantCulture); } - saveTask = storageController + saveTask = AVPlugins.Instance.StorageController .LoadAsync() .OnSuccess(t => t.Result.AddAsync("CurrentUser", JsonConvert.SerializeObject(data))) .Unwrap(); @@ -89,7 +81,7 @@ namespace LeanCloud.Storage.Internal return Task.FromResult(cachedCurrent); } - return storageController.LoadAsync().OnSuccess(t => + return AVPlugins.Instance.StorageController.LoadAsync().OnSuccess(t => { object temp; t.Result.TryGetValue("CurrentUser", out temp); @@ -114,7 +106,7 @@ namespace LeanCloud.Storage.Internal return Task.FromResult(true); } - return storageController.LoadAsync().OnSuccess(t => t.Result.ContainsKey("CurrentUser")); + return AVPlugins.Instance.StorageController.LoadAsync().OnSuccess(t => t.Result.ContainsKey("CurrentUser")); } public bool IsCurrent(AVUser user) @@ -136,7 +128,7 @@ namespace LeanCloud.Storage.Internal { ClearFromMemory(); - storageController.LoadAsync().OnSuccess(t => t.Result.RemoveAsync("CurrentUser")); + AVPlugins.Instance.StorageController.LoadAsync().OnSuccess(t => t.Result.RemoveAsync("CurrentUser")); } } diff --git a/Storage/Storage/Internal/User/Controller/AVUserController.cs b/Storage/Storage/Internal/User/Controller/AVUserController.cs index 2a434d6..0ef656f 100644 --- a/Storage/Storage/Internal/User/Controller/AVUserController.cs +++ b/Storage/Storage/Internal/User/Controller/AVUserController.cs @@ -6,15 +6,8 @@ using System.Net.Http; namespace LeanCloud.Storage.Internal { - public class AVUserController : IAVUserController + public class AVUserController { - private readonly IAVCommandRunner commandRunner; - - public AVUserController(IAVCommandRunner commandRunner) - { - this.commandRunner = commandRunner; - } - public Task SignUpAsync(IObjectState state, IDictionary operations, CancellationToken cancellationToken) @@ -25,7 +18,7 @@ namespace LeanCloud.Storage.Internal Method = HttpMethod.Post, Content = objectJSON }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance); serverState = serverState.MutatedClone(mutableClone => @@ -54,7 +47,7 @@ namespace LeanCloud.Storage.Internal Method = HttpMethod.Post, Content = data }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance); serverState = serverState.MutatedClone(mutableClone => @@ -80,7 +73,7 @@ namespace LeanCloud.Storage.Internal { "authData", authData} } }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance); serverState = serverState.MutatedClone(mutableClone => @@ -97,7 +90,7 @@ namespace LeanCloud.Storage.Internal Path = "users/me", Method = HttpMethod.Get }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance); }); @@ -112,7 +105,7 @@ namespace LeanCloud.Storage.Internal { "email", email} } }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken); + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken); } public Task LogInWithParametersAsync(string relativeUrl, IDictionary data, @@ -123,7 +116,7 @@ namespace LeanCloud.Storage.Internal Method = HttpMethod.Post, Content = data }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance); serverState = serverState.MutatedClone(mutableClone => @@ -144,7 +137,7 @@ namespace LeanCloud.Storage.Internal { "new_password", newPassword }, } }; - return commandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken); + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken); } public Task RefreshSessionTokenAsync(string userId, string sessionToken, diff --git a/Storage/Storage/Internal/User/Controller/IAVCurrentUserController.cs b/Storage/Storage/Internal/User/Controller/IAVCurrentUserController.cs deleted file mode 100644 index c7664aa..0000000 --- a/Storage/Storage/Internal/User/Controller/IAVCurrentUserController.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal { - public interface IAVCurrentUserController : IAVObjectCurrentController { - Task GetCurrentSessionTokenAsync(CancellationToken cancellationToken); - - Task LogOutAsync(CancellationToken cancellationToken); - } -} diff --git a/Storage/Storage/Internal/User/Controller/IAVUserController.cs b/Storage/Storage/Internal/User/Controller/IAVUserController.cs deleted file mode 100644 index 58966a7..0000000 --- a/Storage/Storage/Internal/User/Controller/IAVUserController.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace LeanCloud.Storage.Internal -{ - public interface IAVUserController - { - Task SignUpAsync(IObjectState state, - IDictionary operations, - CancellationToken cancellationToken); - - Task LogInAsync(string username, - string email, - string password, - CancellationToken cancellationToken); - - Task LogInWithParametersAsync(string relativeUrl, - IDictionary data, - CancellationToken cancellationToken); - - Task LogInAsync(string authType, - IDictionary data, - bool failOnNotExist, - CancellationToken cancellationToken); - - Task GetUserAsync(string sessionToken, - CancellationToken cancellationToken); - - Task RequestPasswordResetAsync(string email, - CancellationToken cancellationToken); - - Task UpdatePasswordAsync(string usedId, string sessionToken, - string oldPassword, string newPassword, - CancellationToken cancellationToken); - - Task RefreshSessionTokenAsync(string userId, - string sessionToken, - CancellationToken cancellationToken); - } -} diff --git a/Storage/Storage/Internal/Utilities/AVConfigExtensions.cs b/Storage/Storage/Internal/Utilities/AVConfigExtensions.cs deleted file mode 100644 index 0df396d..0000000 --- a/Storage/Storage/Internal/Utilities/AVConfigExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LeanCloud.Storage.Internal { - /// - /// So here's the deal. We have a lot of internal APIs for AVObject, AVUser, etc. - /// - /// These cannot be 'internal' anymore if we are fully modularizing things out, because - /// they are no longer a part of the same library, especially as we create things like - /// Installation inside push library. - /// - /// So this class contains a bunch of extension methods that can live inside another - /// namespace, which 'wrap' the intenral APIs that already exist. - /// - public static class AVConfigExtensions { - public static AVConfig Create(IDictionary fetchedConfig) { - return new AVConfig(fetchedConfig); - } - } -} diff --git a/Storage/Storage/Public/AVCloud.cs b/Storage/Storage/Public/AVCloud.cs index 7f3f816..9e25f87 100644 --- a/Storage/Storage/Public/AVCloud.cs +++ b/Storage/Storage/Public/AVCloud.cs @@ -21,12 +21,9 @@ namespace LeanCloud { /// await AVCloud.CallFunctionAsync<IDictionary<string, object>>("validateGame", parameters); /// /// - public static class AVCloud - { - internal static IAVCloudCodeController CloudCodeController - { - get - { + public static class AVCloud { + internal static AVCloudCodeController CloudCodeController { + get { return AVPlugins.Instance.CloudCodeController; } } @@ -44,12 +41,10 @@ namespace LeanCloud { /// /// The cancellation token. /// The result of the cloud call. - public static Task CallFunctionAsync(String name, IDictionary parameters = null, string sesstionToken = null, CancellationToken cancellationToken = default(CancellationToken)) - { + public static Task CallFunctionAsync(String name, IDictionary parameters = null, string sesstionToken = null, CancellationToken cancellationToken = default(CancellationToken)) { var sessionTokenTask = AVUser.TakeSessionToken(sesstionToken); - return sessionTokenTask.OnSuccess(s => - { + return sessionTokenTask.OnSuccess(s => { return CloudCodeController.CallFunctionAsync(name, parameters, s.Result, cancellationToken); @@ -66,12 +61,10 @@ namespace LeanCloud { /// /// /// - public static Task RPCFunctionAsync(String name, IDictionary parameters = null, string sesstionToken = null, CancellationToken cancellationToken = default(CancellationToken)) - { + public static Task RPCFunctionAsync(String name, IDictionary parameters = null, string sesstionToken = null, CancellationToken cancellationToken = default(CancellationToken)) { var sessionTokenTask = AVUser.TakeSessionToken(sesstionToken); - return sessionTokenTask.OnSuccess(s => - { + return sessionTokenTask.OnSuccess(s => { return CloudCodeController.RPCFunction(name, parameters, s.Result, @@ -87,8 +80,7 @@ namespace LeanCloud { /// 进行的操作名称。 /// 验证码失效时间。 /// - public static Task RequestSMSCodeAsync(string mobilePhoneNumber, string name, string op, int ttl = 10) - { + public static Task RequestSMSCodeAsync(string mobilePhoneNumber, string name, string op, int ttl = 10) { return RequestSMSCodeAsync(mobilePhoneNumber, name, op, ttl, CancellationToken.None); } @@ -102,10 +94,8 @@ namespace LeanCloud { /// 进行的操作名称。 /// 验证码失效时间。 /// Cancellation token。 - public static Task RequestSMSCodeAsync(string mobilePhoneNumber, string name, string op, int ttl = 10, CancellationToken cancellationToken = default(CancellationToken)) - { - if (string.IsNullOrEmpty(mobilePhoneNumber)) - { + public static Task RequestSMSCodeAsync(string mobilePhoneNumber, string name, string op, int ttl = 10, CancellationToken cancellationToken = default(CancellationToken)) { + if (string.IsNullOrEmpty(mobilePhoneNumber)) { throw new AVException(AVException.ErrorCode.MobilePhoneInvalid, "Moblie Phone number is invalid.", null); } @@ -113,16 +103,13 @@ namespace LeanCloud { { { "mobilePhoneNumber", mobilePhoneNumber }, }; - if (!string.IsNullOrEmpty(name)) - { + if (!string.IsNullOrEmpty(name)) { strs.Add("name", name); } - if (!string.IsNullOrEmpty(op)) - { + if (!string.IsNullOrEmpty(op)) { strs.Add("op", op); } - if (ttl > 0) - { + if (ttl > 0) { strs.Add("TTL", ttl); } var command = new EngineCommand { @@ -138,8 +125,7 @@ namespace LeanCloud { /// /// 是否发送成功。 /// 手机号。 - public static Task RequestSMSCodeAsync(string mobilePhoneNumber) - { + public static Task RequestSMSCodeAsync(string mobilePhoneNumber) { return RequestSMSCodeAsync(mobilePhoneNumber, CancellationToken.None); } @@ -150,8 +136,7 @@ namespace LeanCloud { /// 是否发送成功。 /// 手机号。 /// Cancellation Token. - public static Task RequestSMSCodeAsync(string mobilePhoneNumber, CancellationToken cancellationToken) - { + public static Task RequestSMSCodeAsync(string mobilePhoneNumber, CancellationToken cancellationToken) { return RequestSMSCodeAsync(mobilePhoneNumber, null, null, 0, cancellationToken); } @@ -172,11 +157,9 @@ namespace LeanCloud { IDictionary env, string sign = "", string validateToken = "", - CancellationToken cancellationToken = default(CancellationToken)) - { + CancellationToken cancellationToken = default(CancellationToken)) { - if (string.IsNullOrEmpty(mobilePhoneNumber)) - { + if (string.IsNullOrEmpty(mobilePhoneNumber)) { throw new AVException(AVException.ErrorCode.MobilePhoneInvalid, "Moblie Phone number is invalid.", null); } Dictionary strs = new Dictionary() @@ -184,16 +167,13 @@ namespace LeanCloud { { "mobilePhoneNumber", mobilePhoneNumber }, }; strs.Add("template", template); - if (String.IsNullOrEmpty(sign)) - { + if (String.IsNullOrEmpty(sign)) { strs.Add("sign", sign); } - if (String.IsNullOrEmpty(validateToken)) - { + if (String.IsNullOrEmpty(validateToken)) { strs.Add("validate_token", validateToken); } - foreach (var key in env.Keys) - { + foreach (var key in env.Keys) { strs.Add(key, env[key]); } var command = new EngineCommand { @@ -209,10 +189,8 @@ namespace LeanCloud { /// /// /// - public static Task RequestVoiceCodeAsync(string mobilePhoneNumber) - { - if (string.IsNullOrEmpty(mobilePhoneNumber)) - { + public static Task RequestVoiceCodeAsync(string mobilePhoneNumber) { + if (string.IsNullOrEmpty(mobilePhoneNumber)) { throw new AVException(AVException.ErrorCode.MobilePhoneInvalid, "Moblie Phone number is invalid.", null); } Dictionary body = new Dictionary() @@ -237,8 +215,7 @@ namespace LeanCloud { /// 是否验证通过。 /// 手机号 /// 验证码。 - public static Task VerifySmsCodeAsync(string code, string mobilePhoneNumber) - { + public static Task VerifySmsCodeAsync(string code, string mobilePhoneNumber) { return VerifySmsCodeAsync(code, mobilePhoneNumber, CancellationToken.None); } @@ -249,8 +226,7 @@ namespace LeanCloud { /// 验证码。 /// 手机号 /// Cancellation token. - public static Task VerifySmsCodeAsync(string code, string mobilePhoneNumber, CancellationToken cancellationToken) - { + public static Task VerifySmsCodeAsync(string code, string mobilePhoneNumber, CancellationToken cancellationToken) { var command = new AVCommand { Path = $"verifySmsCode/{code.Trim()}?mobilePhoneNumber={mobilePhoneNumber.Trim()}", }; @@ -260,8 +236,7 @@ namespace LeanCloud { /// /// Stands for a captcha result. /// - public class Captcha - { + public class Captcha { /// /// Used for captcha verify. /// @@ -278,8 +253,7 @@ namespace LeanCloud { /// User's input of this captcha. /// CancellationToken. /// - public Task VerifyAsync(string code, CancellationToken cancellationToken = default(CancellationToken)) - { + public Task VerifyAsync(string code, CancellationToken cancellationToken = default(CancellationToken)) { return AVCloud.VerifyCaptchaAsync(code, Token); } } @@ -291,18 +265,15 @@ namespace LeanCloud { /// captcha image height. /// CancellationToken. /// an instance of Captcha. - public static Task RequestCaptchaAsync(int width = 85, int height = 30, CancellationToken cancellationToken = default(CancellationToken)) - { + public static Task RequestCaptchaAsync(int width = 85, int height = 30, CancellationToken cancellationToken = default(CancellationToken)) { var path = String.Format("requestCaptcha?width={0}&height={1}", width, height); var command = new AVCommand { Path = $"requestCaptcha?width={width}&height={height}", Method = HttpMethod.Get }; - return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => - { + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary; - return new Captcha() - { + return new Captcha() { Token = decoded["captcha_token"] as string, Url = decoded["captcha_url"] as string, }; @@ -316,8 +287,7 @@ namespace LeanCloud { /// User's input of this captcha. /// CancellationToken. /// - public static Task VerifyCaptchaAsync(string code, string token, CancellationToken cancellationToken = default(CancellationToken)) - { + public static Task VerifyCaptchaAsync(string code, string token, CancellationToken cancellationToken = default(CancellationToken)) { var data = new Dictionary { { "captcha_token", token }, { "captcha_code", code }, @@ -327,8 +297,7 @@ namespace LeanCloud { Method = HttpMethod.Post, Content = data }; - return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).ContinueWith(t => - { + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).ContinueWith(t => { if (!t.Result.Item2.ContainsKey("validate_token")) throw new KeyNotFoundException("validate_token"); return t.Result.Item2["validate_token"] as string; @@ -340,38 +309,32 @@ namespace LeanCloud { /// /// /// - public static Task> GetCustomParametersAsync(CancellationToken cancellationToken = default(CancellationToken)) - { + public static Task> GetCustomParametersAsync(CancellationToken cancellationToken = default(CancellationToken)) { var command = new AVCommand { Path = $"statistics/apps/{AVClient.CurrentConfiguration.ApplicationId}/sendPolicy", Method = HttpMethod.Get }; - return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => - { + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).OnSuccess(t => { var settings = t.Result.Item2; var CloudParameters = settings["parameters"] as IDictionary; return CloudParameters; }); } - public class RealtimeSignature - { + public class RealtimeSignature { public string Nonce { internal set; get; } public long Timestamp { internal set; get; } public string ClientId { internal set; get; } public string Signature { internal set; get; } } - public static Task RequestRealtimeSignatureAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - return AVUser.GetCurrentUserAsync(cancellationToken).OnSuccess(t => - { + public static Task RequestRealtimeSignatureAsync(CancellationToken cancellationToken = default(CancellationToken)) { + return AVUser.GetCurrentUserAsync(cancellationToken).OnSuccess(t => { return RequestRealtimeSignatureAsync(t.Result, cancellationToken); }).Unwrap(); } - public static Task RequestRealtimeSignatureAsync(AVUser user, CancellationToken cancellationToken = default(CancellationToken)) - { + public static Task RequestRealtimeSignatureAsync(AVUser user, CancellationToken cancellationToken = default(CancellationToken)) { var command = new AVCommand { Path = "rtm/sign", Method = HttpMethod.Post, @@ -379,11 +342,9 @@ namespace LeanCloud { { "session_token", user.SessionToken } } }; - return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).ContinueWith(t => - { + return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command, cancellationToken: cancellationToken).ContinueWith(t => { var body = t.Result.Item2; - return new RealtimeSignature() - { + return new RealtimeSignature() { Nonce = body["nonce"] as string, Timestamp = (long)body["timestamp"], ClientId = body["client_id"] as string, @@ -396,8 +357,7 @@ namespace LeanCloud { /// Gets the LeanEngine hosting URL for current app async. /// /// The lean engine hosting URL async. - public static Task GetLeanEngineHostingUrlAsync() - { + public static Task GetLeanEngineHostingUrlAsync() { return CallFunctionAsync("_internal_extensions_get_domain"); } @@ -407,8 +367,7 @@ namespace LeanCloud { /// /// AVRPCC loud function base. /// - public class AVRPCCloudFunctionBase - { + public class AVRPCCloudFunctionBase { /// /// AVRPCD eserialize. /// @@ -419,17 +378,13 @@ namespace LeanCloud { public delegate IDictionary AVRPCSerialize

(P parameters); public AVRPCCloudFunctionBase() - : this(true) - { + : this(true) { } - public AVRPCCloudFunctionBase(bool noneParameters) - { - if (noneParameters) - { - this.Encode = n => - { + public AVRPCCloudFunctionBase(bool noneParameters) { + if (noneParameters) { + this.Encode = n => { return null; }; } @@ -438,28 +393,21 @@ namespace LeanCloud { private AVRPCDeserialize _decode; - public AVRPCDeserialize Decode - { - get - { + public AVRPCDeserialize Decode { + get { return _decode; } - set - { + set { _decode = value; } } private AVRPCSerialize

_encode; - public AVRPCSerialize

Encode - { - get - { - if (_encode == null) - { - _encode = n => - { + public AVRPCSerialize

Encode { + get { + if (_encode == null) { + _encode = n => { if (n != null) { return JsonConvert.DeserializeObject>(n.ToString(), new LeanCloudJsonConverter()); } @@ -468,18 +416,15 @@ namespace LeanCloud { } return _encode; } - set - { + set { _encode = value; } } public string FunctionName { get; set; } - public Task ExecuteAsync(P parameters) - { - return AVUser.GetCurrentAsync().OnSuccess(t => - { + public Task ExecuteAsync(P parameters) { + return AVUser.GetCurrentAsync().OnSuccess(t => { var user = t.Result; var encodedParameters = Encode(parameters); var command = new EngineCommand { @@ -488,11 +433,9 @@ namespace LeanCloud { Content = encodedParameters }; return AVPlugins.Instance.CommandRunner.RunCommandAsync>(command); - }).Unwrap().OnSuccess(s => - { + }).Unwrap().OnSuccess(s => { var responseBody = s.Result.Item2; - if (!responseBody.ContainsKey("result")) - { + if (!responseBody.ContainsKey("result")) { return default(R); } @@ -503,31 +446,24 @@ namespace LeanCloud { } - public class AVObjectRPCCloudFunction : AVObjectRPCCloudFunction - { + public class AVObjectRPCCloudFunction : AVObjectRPCCloudFunction { } - public class AVObjectListRPCCloudFunction : AVObjectListRPCCloudFunction - { + public class AVObjectListRPCCloudFunction : AVObjectListRPCCloudFunction { } - public class AVObjectListRPCCloudFunction : AVRPCCloudFunctionBase> where R : AVObject - { + public class AVObjectListRPCCloudFunction : AVRPCCloudFunctionBase> where R : AVObject { public AVObjectListRPCCloudFunction() - : base(true) - { + : base(true) { this.Decode = this.AVObjectListDeserializer(); } - public AVRPCDeserialize> AVObjectListDeserializer() - { - AVRPCDeserialize> del = data => - { + public AVRPCDeserialize> AVObjectListDeserializer() { + AVRPCDeserialize> del = data => { var items = data["result"] as IList; - return items.Select(item => - { + return items.Select(item => { var state = AVObjectCoder.Instance.Decode(item as IDictionary, AVDecoder.Instance); return AVObject.FromState(state, state.ClassName); }).ToList() as IList; @@ -537,19 +473,15 @@ namespace LeanCloud { } } - public class AVObjectRPCCloudFunction : AVRPCCloudFunctionBase where R : AVObject - { + public class AVObjectRPCCloudFunction : AVRPCCloudFunctionBase where R : AVObject { public AVObjectRPCCloudFunction() - : base(true) - { + : base(true) { this.Decode = this.AVObjectDeserializer(); } - public AVRPCDeserialize AVObjectDeserializer() - { - AVRPCDeserialize del = data => - { + public AVRPCDeserialize AVObjectDeserializer() { + AVRPCDeserialize del = data => { var item = data["result"] as object; var state = AVObjectCoder.Instance.Decode(item as IDictionary, AVDecoder.Instance); diff --git a/Storage/Storage/Public/AVConfig.cs b/Storage/Storage/Public/AVConfig.cs deleted file mode 100644 index 8e3b041..0000000 --- a/Storage/Storage/Public/AVConfig.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using LeanCloud.Storage.Internal; -using LeanCloud.Utilities; - -namespace LeanCloud -{ - /// - /// The AVConfig is a representation of the remote configuration object, - /// that enables you to add things like feature gating, a/b testing or simple "Message of the day". - /// - public class AVConfig : IJsonConvertible - { - private IDictionary properties = new Dictionary(); - - /// - /// Gets the latest fetched AVConfig. - /// - /// AVConfig object - public static AVConfig CurrentConfig - { - get - { - Task task = ConfigController.CurrentConfigController.GetCurrentConfigAsync(); - task.Wait(); - return task.Result; - } - } - - internal static void ClearCurrentConfig() - { - ConfigController.CurrentConfigController.ClearCurrentConfigAsync().Wait(); - } - - internal static void ClearCurrentConfigInMemory() - { - ConfigController.CurrentConfigController.ClearCurrentConfigInMemoryAsync().Wait(); - } - - private static IAVConfigController ConfigController - { - get { return AVPlugins.Instance.ConfigController; } - } - - internal AVConfig() - : base() - { - } - - internal AVConfig(IDictionary fetchedConfig) - { - var props = AVDecoder.Instance.Decode(fetchedConfig["params"]) as IDictionary; - properties = props; - } - - /// - /// Retrieves the AVConfig asynchronously from the server. - /// - /// AVConfig object that was fetched - public static Task GetAsync() - { - return GetAsync(CancellationToken.None); - } - - /// - /// Retrieves the AVConfig asynchronously from the server. - /// - /// The cancellation token. - /// AVConfig object that was fetched - public static Task GetAsync(CancellationToken cancellationToken) - { - return ConfigController.FetchConfigAsync(AVUser.CurrentSessionToken, cancellationToken); - } - - /// - /// Gets a value for the key of a particular type. - /// - /// The type to convert the value to. Supported types are - /// AVObject and its descendents, LeanCloud types such as AVRelation and AVGeopoint, - /// primitive types,IList<T>, IDictionary<string, T> and strings. - /// The key of the element to get. - /// The property is retrieved - /// and is not found. - /// The property under this - /// key was found, but of a different type. - public T Get(string key) - { - return Conversion.To(this.properties[key]); - } - - /// - /// Populates result with the value for the key, if possible. - /// - /// The desired type for the value. - /// The key to retrieve a value for. - /// The value for the given key, converted to the - /// requested type, or null if unsuccessful. - /// true if the lookup and conversion succeeded, otherwise false. - public bool TryGetValue(string key, out T result) - { - if (this.properties.ContainsKey(key)) - { - try - { - var temp = Conversion.To(this.properties[key]); - result = temp; - return true; - } - catch (Exception) - { - // Could not convert, do nothing - } - } - result = default(T); - return false; - } - - /// - /// Gets a value on the config. - /// - /// The key for the parameter. - /// The property is - /// retrieved and is not found. - /// The value for the key. - virtual public object this[string key] - { - get - { - return this.properties[key]; - } - } - - IDictionary IJsonConvertible.ToJSON() - { - return new Dictionary { - { "params", NoObjectsEncoder.Instance.Encode(properties) } - }; - } - } -} diff --git a/Storage/Storage/Public/AVFile.cs b/Storage/Storage/Public/AVFile.cs index 3a1ec57..e4f06bc 100644 --- a/Storage/Storage/Public/AVFile.cs +++ b/Storage/Storage/Public/AVFile.cs @@ -272,7 +272,7 @@ namespace LeanCloud } } - internal static IAVFileController FileController + internal static AVFileController FileController { get { diff --git a/Storage/Storage/Public/AVObject.cs b/Storage/Storage/Public/AVObject.cs index 984bf63..12ac035 100644 --- a/Storage/Storage/Public/AVObject.cs +++ b/Storage/Storage/Public/AVObject.cs @@ -11,8 +11,7 @@ using System.Threading; using System.Threading.Tasks; using System.Collections; -namespace LeanCloud -{ +namespace LeanCloud { /// /// The AVObject is a local representation of data that can be saved and /// retrieved from the LeanCloud cloud. @@ -27,8 +26,7 @@ namespace LeanCloud /// to specify which existing data to retrieve. /// /// - public class AVObject : IEnumerable>, INotifyPropertyChanged, INotifyPropertyUpdated, INotifyCollectionPropertyUpdated - { + public class AVObject : IEnumerable>, INotifyPropertyChanged, INotifyPropertyUpdated, INotifyCollectionPropertyUpdated { private static readonly string AutoClassName = "_Automatic"; #if UNITY @@ -51,10 +49,8 @@ namespace LeanCloud internal TaskQueue taskQueue = new TaskQueue(); private IObjectState state; - internal void MutateState(Action func) - { - lock (mutex) - { + internal void MutateState(Action func) { + lock (mutex) { state = state.MutatedClone(func); // Refresh the estimated data. @@ -62,32 +58,25 @@ namespace LeanCloud } } - public IObjectState State - { - get - { + public IObjectState State { + get { return state; } } - internal static IAVObjectController ObjectController - { - get - { + internal static AVObjectController ObjectController { + get { return AVPlugins.Instance.ObjectController; } } - internal static IObjectSubclassingController SubclassingController - { - get - { + internal static ObjectSubclassingController SubclassingController { + get { return AVPlugins.Instance.SubclassingController; } } - public static string GetSubClassName() - { + public static string GetSubClassName() { return SubclassingController.GetClassName(typeof(TAVObject)); } @@ -97,8 +86,7 @@ namespace LeanCloud /// Constructor for use in AVObject subclasses. Subclasses must specify a AVClassName attribute. /// protected AVObject() - : this(AutoClassName) - { + : this(AutoClassName) { } /// @@ -111,8 +99,7 @@ namespace LeanCloud /// to name classes in CamelCaseLikeThis. /// /// The className for this AVObject. - public AVObject(string className) - { + public AVObject(string className) { // We use a ThreadLocal rather than passing a parameter so that createWithoutData can do the // right thing with subclasses. It's ugly and terrible, but it does provide the development // experience we generally want, so... yeah. Sorry to whomever has to deal with this in the @@ -120,35 +107,28 @@ namespace LeanCloud var isPointer = isCreatingPointer.Value; isCreatingPointer.Value = false; - if (className == null) - { + if (className == null) { throw new ArgumentException("You must specify a LeanCloud class name when creating a new AVObject."); } - if (AutoClassName.Equals(className)) - { + if (AutoClassName.Equals(className)) { className = SubclassingController.GetClassName(GetType()); } // If this is supposed to be created by a factory but wasn't, throw an exception - if (!SubclassingController.IsTypeValid(className, GetType())) - { + if (!SubclassingController.IsTypeValid(className, GetType())) { throw new ArgumentException( "You must create this type of AVObject using AVObject.Create() or the proper subclass."); } - state = new MutableObjectState - { + state = new MutableObjectState { ClassName = className }; OnPropertyChanged("ClassName"); operationSetQueue.AddLast(new Dictionary()); - if (!isPointer) - { + if (!isPointer) { hasBeenFetched = true; IsDirty = true; SetDefaultValues(); - } - else - { + } else { IsDirty = false; hasBeenFetched = false; } @@ -160,8 +140,7 @@ namespace LeanCloud /// /// The class of object to create. /// A new AVObject for the given class name. - public static AVObject Create(string className) - { + public static AVObject Create(string className) { return SubclassingController.Instantiate(className); } @@ -174,23 +153,18 @@ namespace LeanCloud /// The object's class. /// The object id for the referenced object. /// A AVObject without data. - public static AVObject CreateWithoutData(string className, string objectId) - { + public static AVObject CreateWithoutData(string className, string objectId) { isCreatingPointer.Value = true; - try - { + try { var result = SubclassingController.Instantiate(className); result.ObjectId = objectId; result.IsDirty = false; - if (result.IsDirty) - { + if (result.IsDirty) { throw new InvalidOperationException( "A AVObject subclass default constructor must not make changes to the object that cause it to be dirty."); } return result; - } - finally - { + } finally { isCreatingPointer.Value = false; } } @@ -199,8 +173,7 @@ namespace LeanCloud /// Creates a new AVObject based upon a given subclass type. /// /// A new AVObject for the given class name. - public static T Create() where T : AVObject - { + public static T Create() where T : AVObject { return (T)SubclassingController.Instantiate(SubclassingController.GetClassName(typeof(T))); } @@ -212,8 +185,7 @@ namespace LeanCloud /// /// The object id for the referenced object. /// A AVObject without data. - public static T CreateWithoutData(string objectId) where T : AVObject - { + public static T CreateWithoutData(string objectId) where T : AVObject { return (T)CreateWithoutData(SubclassingController.GetClassName(typeof(T)), objectId); } @@ -222,8 +194,7 @@ namespace LeanCloud /// /// IObjectState after encode from Dictionary. /// The name of the subclass. - public static T FromState(IObjectState state, string defaultClassName) where T : AVObject - { + public static T FromState(IObjectState state, string defaultClassName) where T : AVObject { string className = state.ClassName ?? defaultClassName; T obj = (T)CreateWithoutData(className, state.ObjectId); @@ -234,13 +205,11 @@ namespace LeanCloud #endregion - public static IDictionary GetPropertyMappings(string className) - { + public static IDictionary GetPropertyMappings(string className) { return SubclassingController.GetPropertyMappings(className); } - private static string GetFieldForPropertyName(string className, string propertyName) - { + private static string GetFieldForPropertyName(string className, string propertyName) { String fieldName = null; SubclassingController.GetPropertyMappings(className).TryGetValue(propertyName, out fieldName); return fieldName; @@ -258,8 +227,7 @@ namespace LeanCloud #else string propertyName #endif -) - { +) { this[GetFieldForPropertyName(ClassName, propertyName)] = value; } @@ -275,8 +243,7 @@ namespace LeanCloud #else string propertyName #endif -) where T : AVObject - { +) where T : AVObject { return GetRelation(GetFieldForPropertyName(ClassName, propertyName)); } @@ -292,8 +259,7 @@ string propertyName #else string propertyName #endif -) - { +) { return GetProperty(default(T), propertyName); } @@ -310,11 +276,9 @@ string propertyName #else string propertyName #endif -) - { +) { T result; - if (TryGetValue(GetFieldForPropertyName(ClassName, propertyName), out result)) - { + if (TryGetValue(GetFieldForPropertyName(ClassName, propertyName), out result)) { return result; } return defaultValue; @@ -323,8 +287,7 @@ string propertyName /// /// Allows subclasses to set values for non-pointer construction. /// - internal virtual void SetDefaultValues() - { + internal virtual void SetDefaultValues() { } /// @@ -333,26 +296,21 @@ string propertyName /// backed by AVObject fields should have AVFieldName attributes supplied. /// /// The AVObject subclass type to register. - public static void RegisterSubclass() where T : AVObject, new() - { + public static void RegisterSubclass() where T : AVObject, new() { SubclassingController.RegisterSubclass(typeof(T)); } - internal static void UnregisterSubclass() where T : AVObject, new() - { + internal static void UnregisterSubclass() where T : AVObject, new() { SubclassingController.UnregisterSubclass(typeof(T)); } /// /// Clears any changes to this object made since the last call to . /// - public void Revert() - { - lock (mutex) - { + public void Revert() { + lock (mutex) { bool wasDirty = CurrentOperations.Count > 0; - if (wasDirty) - { + if (wasDirty) { CurrentOperations.Clear(); RebuildEstimatedData(); OnPropertyChanged("IsDirty"); @@ -360,50 +318,39 @@ string propertyName } } - internal virtual void HandleFetchResult(IObjectState serverState) - { - lock (mutex) - { + internal virtual void HandleFetchResult(IObjectState serverState) { + lock (mutex) { MergeFromServer(serverState); } } internal void HandleFailedSave( - IDictionary operationsBeforeSave) - { - lock (mutex) - { + IDictionary operationsBeforeSave) { + lock (mutex) { var opNode = operationSetQueue.Find(operationsBeforeSave); var nextOperations = opNode.Next.Value; bool wasDirty = nextOperations.Count > 0; operationSetQueue.Remove(opNode); // Merge the data from the failed save into the next save. - foreach (var pair in operationsBeforeSave) - { + foreach (var pair in operationsBeforeSave) { var operation1 = pair.Value; IAVFieldOperation operation2 = null; nextOperations.TryGetValue(pair.Key, out operation2); - if (operation2 != null) - { + if (operation2 != null) { operation2 = operation2.MergeWithPrevious(operation1); - } - else - { + } else { operation2 = operation1; } nextOperations[pair.Key] = operation2; } - if (!wasDirty && nextOperations == CurrentOperations && operationsBeforeSave.Count > 0) - { + if (!wasDirty && nextOperations == CurrentOperations && operationsBeforeSave.Count > 0) { OnPropertyChanged("IsDirty"); } } } - internal virtual void HandleSave(IObjectState serverState) - { - lock (mutex) - { + internal virtual void HandleSave(IObjectState serverState) { + lock (mutex) { var operationsBeforeSave = operationSetQueue.First.Value; operationSetQueue.RemoveFirst(); @@ -417,28 +364,23 @@ string propertyName } } - public virtual void MergeFromServer(IObjectState serverState) - { + public virtual void MergeFromServer(IObjectState serverState) { // Make a new serverData with fetched values. var newServerData = serverState.ToDictionary(t => t.Key, t => t.Value); - lock (mutex) - { + lock (mutex) { // Trigger handler based on serverState - if (serverState.ObjectId != null) - { + if (serverState.ObjectId != null) { // If the objectId is being merged in, consider this object to be fetched. hasBeenFetched = true; OnPropertyChanged("IsDataAvailable"); } - if (serverState.UpdatedAt != null) - { + if (serverState.UpdatedAt != null) { OnPropertyChanged("UpdatedAt"); } - if (serverState.CreatedAt != null) - { + if (serverState.CreatedAt != null) { OnPropertyChanged("CreatedAt"); } @@ -446,15 +388,12 @@ string propertyName // the fetched objects into Pointers. IDictionary fetchedObject = CollectFetchedObjects(); - foreach (var pair in serverState) - { + foreach (var pair in serverState) { var value = pair.Value; - if (value is AVObject) - { + if (value is AVObject) { // Resolve fetched object. var avObject = value as AVObject; - if (fetchedObject.ContainsKey(avObject.ObjectId)) - { + if (fetchedObject.ContainsKey(avObject.ObjectId)) { value = fetchedObject[avObject.ObjectId]; } } @@ -462,53 +401,42 @@ string propertyName } IsDirty = false; - serverState = serverState.MutatedClone(mutableClone => - { + serverState = serverState.MutatedClone(mutableClone => { mutableClone.ServerData = newServerData; }); - MutateState(mutableClone => - { + MutateState(mutableClone => { mutableClone.Apply(serverState); }); } } - internal void MergeFromObject(AVObject other) - { - lock (mutex) - { + internal void MergeFromObject(AVObject other) { + lock (mutex) { // If they point to the same instance, we don't need to merge - if (this == other) - { + if (this == other) { return; } } // Clear out any changes on this object. - if (operationSetQueue.Count != 1) - { + if (operationSetQueue.Count != 1) { throw new InvalidOperationException("Attempt to MergeFromObject during save."); } operationSetQueue.Clear(); - foreach (var operationSet in other.operationSetQueue) - { + foreach (var operationSet in other.operationSetQueue) { operationSetQueue.AddLast(operationSet.ToDictionary(entry => entry.Key, entry => entry.Value)); } - lock (mutex) - { + lock (mutex) { state = other.State; } RebuildEstimatedData(); } - private bool HasDirtyChildren - { - get - { - lock (mutex) - { + private bool HasDirtyChildren { + get { + lock (mutex) { return FindUnsavedChildren().FirstOrDefault() != null; } } @@ -523,57 +451,41 @@ string propertyName /// Whether to include the root in the result /// internal static IEnumerable DeepTraversal( - object root, bool traverseAVObjects = false, bool yieldRoot = false) - { + object root, bool traverseAVObjects = false, bool yieldRoot = false) { var items = DeepTraversalInternal(root, traverseAVObjects, new HashSet(new IdentityEqualityComparer())); - if (yieldRoot) - { + if (yieldRoot) { return new[] { root }.Concat(items); - } - else - { + } else { return items; } } private static IEnumerable DeepTraversalInternal( - object root, bool traverseAVObjects, ICollection seen) - { + object root, bool traverseAVObjects, ICollection seen) { seen.Add(root); var itemsToVisit = isCompiledByIL2CPP ? (System.Collections.IEnumerable)null : (IEnumerable)null; var dict = Conversion.As>(root); - if (dict != null) - { + if (dict != null) { itemsToVisit = dict.Values; - } - else - { + } else { var list = Conversion.As>(root); - if (list != null) - { + if (list != null) { itemsToVisit = list; - } - else if (traverseAVObjects) - { + } else if (traverseAVObjects) { var obj = root as AVObject; - if (obj != null) - { + if (obj != null) { itemsToVisit = obj.Keys.ToList().Select(k => obj[k]); } } } - if (itemsToVisit != null) - { - foreach (var i in itemsToVisit) - { - if (!seen.Contains(i)) - { + if (itemsToVisit != null) { + foreach (var i in itemsToVisit) { + if (!seen.Contains(i)) { yield return i; var children = DeepTraversalInternal(i, traverseAVObjects, seen); - foreach (var child in children) - { + foreach (var child in children) { yield return child; } } @@ -581,8 +493,7 @@ string propertyName } } - private IEnumerable FindUnsavedChildren() - { + private IEnumerable FindUnsavedChildren() { return DeepTraversal(estimatedData) .OfType() .Where(o => o.IsDirty); @@ -594,8 +505,7 @@ string propertyName /// refreshing or saving. /// /// Map of objectId to AVObject which have been fetched. - private IDictionary CollectFetchedObjects() - { + private IDictionary CollectFetchedObjects() { return DeepTraversal(estimatedData) .OfType() .Where(o => o.ObjectId != null && o.IsDataAvailable) @@ -604,11 +514,9 @@ string propertyName } public static IDictionary ToJSONObjectForSaving( - IDictionary operations) - { + IDictionary operations) { var result = new Dictionary(); - foreach (var pair in operations) - { + foreach (var pair in operations) { // AVRPCSerialize the data var operation = pair.Value; @@ -617,13 +525,10 @@ string propertyName return result; } - internal IDictionary EncodeForSaving(IDictionary data) - { + internal IDictionary EncodeForSaving(IDictionary data) { var result = new Dictionary(); - lock (this.mutex) - { - foreach (var key in data.Keys) - { + lock (this.mutex) { + foreach (var key in data.Keys) { var value = data[key]; result.Add(key, PointerOrLocalIdEncoder.Instance.Encode(value)); } @@ -633,8 +538,7 @@ string propertyName } - internal IDictionary ServerDataToJSONObjectForSerialization() - { + internal IDictionary ServerDataToJSONObjectForSerialization() { return PointerOrLocalIdEncoder.Instance.Encode(state.ToDictionary(t => t.Key, t => t.Value)) as IDictionary; } @@ -644,10 +548,8 @@ string propertyName /// /// Pushes new operations onto the queue and returns the current set of operations. /// - public IDictionary StartSave() - { - lock (mutex) - { + public IDictionary StartSave() { + lock (mutex) { var currentOperations = CurrentOperations; operationSetQueue.AddLast(new Dictionary()); OnPropertyChanged("IsDirty"); @@ -656,18 +558,15 @@ string propertyName } protected virtual Task SaveAsync(Task toAwait, - CancellationToken cancellationToken) - { + CancellationToken cancellationToken) { IDictionary currentOperations = null; - if (!IsDirty) - { + if (!IsDirty) { return Task.FromResult(0); } Task deepSaveTask; string sessionToken; - lock (mutex) - { + lock (mutex) { // Get the JSON representation of the object. currentOperations = StartSave(); @@ -676,23 +575,17 @@ string propertyName deepSaveTask = DeepSaveAsync(estimatedData, sessionToken, cancellationToken); } - return deepSaveTask.OnSuccess(_ => - { + return deepSaveTask.OnSuccess(_ => { return toAwait; - }).Unwrap().OnSuccess(_ => - { + }).Unwrap().OnSuccess(_ => { return ObjectController.SaveAsync(state, currentOperations, sessionToken, cancellationToken); - }).Unwrap().ContinueWith(t => - { - if (t.IsFaulted || t.IsCanceled) - { + }).Unwrap().ContinueWith(t => { + if (t.IsFaulted || t.IsCanceled) { HandleFailedSave(currentOperations); - } - else - { + } else { var serverState = t.Result; HandleSave(serverState); } @@ -703,8 +596,7 @@ string propertyName /// /// Saves this object to the server. /// - public virtual Task SaveAsync() - { + public virtual Task SaveAsync() { return SaveAsync(CancellationToken.None); } @@ -712,8 +604,7 @@ string propertyName /// Saves this object to the server. /// /// The cancellation token. - public virtual Task SaveAsync(CancellationToken cancellationToken) - { + public virtual Task SaveAsync(CancellationToken cancellationToken) { return taskQueue.Enqueue(toAwait => SaveAsync(toAwait, cancellationToken), cancellationToken); } @@ -721,29 +612,23 @@ string propertyName internal virtual Task FetchAsyncInternal( Task toAwait, IDictionary queryString, - CancellationToken cancellationToken) - { - return toAwait.OnSuccess(_ => - { - if (ObjectId == null) - { + CancellationToken cancellationToken) { + return toAwait.OnSuccess(_ => { + if (ObjectId == null) { throw new InvalidOperationException("Cannot refresh an object that hasn't been saved to the server."); } - if (queryString == null) - { + if (queryString == null) { queryString = new Dictionary(); } return ObjectController.FetchAsync(state, queryString, AVUser.CurrentSessionToken, cancellationToken); - }).Unwrap().OnSuccess(t => - { + }).Unwrap().OnSuccess(t => { HandleFetchResult(t.Result); return this; }); } - private static Task DeepSaveAsync(object obj, string sessionToken, CancellationToken cancellationToken) - { + private static Task DeepSaveAsync(object obj, string sessionToken, CancellationToken cancellationToken) { var objects = new List(); CollectDirtyChildren(obj, objects); @@ -755,11 +640,9 @@ string propertyName .Where(f => f.IsDirty) .Select(f => f.SaveAsync(cancellationToken)).ToList(); - return Task.WhenAll(saveDirtyFileTasks).OnSuccess(_ => - { + return Task.WhenAll(saveDirtyFileTasks).OnSuccess(_ => { IEnumerable remaining = new List(uniqueObjects); - return InternalExtensions.WhileAsync(() => Task.FromResult(remaining.Any()), () => - { + return InternalExtensions.WhileAsync(() => Task.FromResult(remaining.Any()), () => { // Partition the objects into two sets: those that can be saved immediately, // and those that rely on other objects to be created first. var current = (from item in remaining @@ -770,8 +653,7 @@ string propertyName select item).ToList(); remaining = nextBatch; - if (current.Count == 0) - { + if (current.Count == 0) { // We do cycle-detection when building the list of objects passed to this // function, so this should never get called. But we should check for it // anyway, so that we get an exception instead of an infinite loop. @@ -780,10 +662,8 @@ string propertyName } // Save all of the objects in current. - return AVObject.EnqueueForAll(current, toAwait => - { - return toAwait.OnSuccess(__ => - { + return AVObject.EnqueueForAll(current, toAwait => { + return toAwait.OnSuccess(__ => { var states = (from item in current select item.state).ToList(); var operationsList = (from item in current @@ -794,20 +674,14 @@ string propertyName sessionToken, cancellationToken); - return Task.WhenAll(saveTasks).ContinueWith(t => - { - if (t.IsFaulted || t.IsCanceled) - { - foreach (var pair in current.Zip(operationsList, (item, ops) => new { item, ops })) - { + return Task.WhenAll(saveTasks).ContinueWith(t => { + if (t.IsFaulted || t.IsCanceled) { + foreach (var pair in current.Zip(operationsList, (item, ops) => new { item, ops })) { pair.item.HandleFailedSave(pair.ops); } - } - else - { + } else { var serverStates = t.Result; - foreach (var pair in current.Zip(serverStates, (item, state) => new { item, state })) - { + foreach (var pair in current.Zip(serverStates, (item, state) => new { item, state })) { pair.item.HandleSave(pair.state); } } @@ -824,8 +698,7 @@ string propertyName /// Saves each object in the provided list. /// /// The objects to save. - public static Task SaveAllAsync(IEnumerable objects) where T : AVObject - { + public static Task SaveAllAsync(IEnumerable objects) where T : AVObject { return SaveAllAsync(objects, CancellationToken.None); } @@ -835,8 +708,7 @@ string propertyName /// The objects to save. /// The cancellation token. public static Task SaveAllAsync( - IEnumerable objects, CancellationToken cancellationToken) where T : AVObject - { + IEnumerable objects, CancellationToken cancellationToken) where T : AVObject { return DeepSaveAsync(objects.ToList(), AVUser.CurrentSessionToken, cancellationToken); } @@ -848,22 +720,18 @@ string propertyName /// Fetches this object with the data from the server. /// /// The cancellation token. - internal Task FetchAsyncInternal(CancellationToken cancellationToken) - { + internal Task FetchAsyncInternal(CancellationToken cancellationToken) { return FetchAsyncInternal(null, cancellationToken); } - internal Task FetchAsyncInternal(IDictionary queryString, CancellationToken cancellationToken) - { + internal Task FetchAsyncInternal(IDictionary queryString, CancellationToken cancellationToken) { return taskQueue.Enqueue(toAwait => FetchAsyncInternal(toAwait, queryString, cancellationToken), cancellationToken); } internal Task FetchIfNeededAsyncInternal( - Task toAwait, CancellationToken cancellationToken) - { - if (!IsDataAvailable) - { + Task toAwait, CancellationToken cancellationToken) { + if (!IsDataAvailable) { return FetchAsyncInternal(toAwait, null, cancellationToken); } return Task.FromResult(this); @@ -874,8 +742,7 @@ string propertyName /// false), fetches this object with the data from the server. /// /// The cancellation token. - internal Task FetchIfNeededAsyncInternal(CancellationToken cancellationToken) - { + internal Task FetchIfNeededAsyncInternal(CancellationToken cancellationToken) { return taskQueue.Enqueue(toAwait => FetchIfNeededAsyncInternal(toAwait, cancellationToken), cancellationToken); } @@ -885,8 +752,7 @@ string propertyName /// /// The list passed in for convenience. public static Task> FetchAllIfNeededAsync( - IEnumerable objects) where T : AVObject - { + IEnumerable objects) where T : AVObject { return FetchAllIfNeededAsync(objects, CancellationToken.None); } @@ -897,10 +763,8 @@ string propertyName /// The cancellation token. /// The list passed in for convenience. public static Task> FetchAllIfNeededAsync( - IEnumerable objects, CancellationToken cancellationToken) where T : AVObject - { - return AVObject.EnqueueForAll(objects.Cast(), (Task toAwait) => - { + IEnumerable objects, CancellationToken cancellationToken) where T : AVObject { + return AVObject.EnqueueForAll(objects.Cast(), (Task toAwait) => { return FetchAllInternalAsync(objects, false, toAwait, cancellationToken); }, cancellationToken); } @@ -911,8 +775,7 @@ string propertyName /// The objects to fetch. /// The list passed in for convenience. public static Task> FetchAllAsync( - IEnumerable objects) where T : AVObject - { + IEnumerable objects) where T : AVObject { return FetchAllAsync(objects, CancellationToken.None); } @@ -923,10 +786,8 @@ string propertyName /// The cancellation token. /// The list passed in for convenience. public static Task> FetchAllAsync( - IEnumerable objects, CancellationToken cancellationToken) where T : AVObject - { - return AVObject.EnqueueForAll(objects.Cast(), (Task toAwait) => - { + IEnumerable objects, CancellationToken cancellationToken) where T : AVObject { + return AVObject.EnqueueForAll(objects.Cast(), (Task toAwait) => { return FetchAllInternalAsync(objects, true, toAwait, cancellationToken); }, cancellationToken); } @@ -940,12 +801,9 @@ string propertyName /// The cancellation token. /// The list passed in for convenience. private static Task> FetchAllInternalAsync( - IEnumerable objects, bool force, Task toAwait, CancellationToken cancellationToken) where T : AVObject - { - return toAwait.OnSuccess(_ => - { - if (objects.Any(obj => { return obj.state.ObjectId == null; })) - { + IEnumerable objects, bool force, Task toAwait, CancellationToken cancellationToken) where T : AVObject { + return toAwait.OnSuccess(_ => { + if (objects.Any(obj => { return obj.state.ObjectId == null; })) { throw new InvalidOperationException("You cannot fetch objects that haven't already been saved."); } @@ -953,8 +811,7 @@ string propertyName where force || !obj.IsDataAvailable select obj).ToList(); - if (objectsToFetch.Count == 0) - { + if (objectsToFetch.Count == 0) { return Task.FromResult(objects); } @@ -963,8 +820,7 @@ string propertyName (from obj in objectsToFetch group obj.ObjectId by obj.ClassName into classGroup where classGroup.Count() > 0 - select new - { + select new { ClassName = classGroup.Key, FindTask = new AVQuery(classGroup.Key) .WhereContainedIn("objectId", classGroup) @@ -972,10 +828,8 @@ string propertyName }).ToDictionary(pair => pair.ClassName, pair => pair.FindTask); // Wait for all the Finds to complete. - return Task.WhenAll(findsByClass.Values.ToList()).OnSuccess(__ => - { - if (cancellationToken.IsCancellationRequested) - { + return Task.WhenAll(findsByClass.Values.ToList()).OnSuccess(__ => { + if (cancellationToken.IsCancellationRequested) { return objects; } @@ -984,8 +838,7 @@ string propertyName from result in findsByClass[obj.ClassName].Result where result.ObjectId == obj.ObjectId select new { obj, result }; - foreach (var pair in pairs) - { + foreach (var pair in pairs) { pair.obj.MergeFromObject(pair.result); pair.obj.hasBeenFetched = true; } @@ -999,17 +852,14 @@ string propertyName #region Delete Object - internal Task DeleteAsync(Task toAwait, CancellationToken cancellationToken) - { - if (ObjectId == null) - { + internal Task DeleteAsync(Task toAwait, CancellationToken cancellationToken) { + if (ObjectId == null) { return Task.FromResult(0); } string sessionToken = AVUser.CurrentSessionToken; - return toAwait.OnSuccess(_ => - { + return toAwait.OnSuccess(_ => { return ObjectController.DeleteAsync(State, sessionToken, cancellationToken); }).Unwrap().OnSuccess(_ => IsDirty = true); } @@ -1017,8 +867,7 @@ string propertyName /// /// Deletes this object on the server. /// - public Task DeleteAsync() - { + public Task DeleteAsync() { return DeleteAsync(CancellationToken.None); } @@ -1026,8 +875,7 @@ string propertyName /// Deletes this object on the server. /// /// The cancellation token. - public Task DeleteAsync(CancellationToken cancellationToken) - { + public Task DeleteAsync(CancellationToken cancellationToken) { return taskQueue.Enqueue(toAwait => DeleteAsync(toAwait, cancellationToken), cancellationToken); } @@ -1036,8 +884,7 @@ string propertyName /// Deletes each object in the provided list. /// /// The objects to delete. - public static Task DeleteAllAsync(IEnumerable objects) where T : AVObject - { + public static Task DeleteAllAsync(IEnumerable objects) where T : AVObject { return DeleteAllAsync(objects, CancellationToken.None); } @@ -1047,26 +894,21 @@ string propertyName /// The objects to delete. /// The cancellation token. public static Task DeleteAllAsync( - IEnumerable objects, CancellationToken cancellationToken) where T : AVObject - { + IEnumerable objects, CancellationToken cancellationToken) where T : AVObject { var uniqueObjects = new HashSet(objects.OfType().ToList(), new IdentityEqualityComparer()); - return AVObject.EnqueueForAll(uniqueObjects, toAwait => - { + return AVObject.EnqueueForAll(uniqueObjects, toAwait => { var states = uniqueObjects.Select(t => t.state).ToList(); - return toAwait.OnSuccess(_ => - { + return toAwait.OnSuccess(_ => { var deleteTasks = ObjectController.DeleteAllAsync(states, AVUser.CurrentSessionToken, cancellationToken); return Task.WhenAll(deleteTasks); - }).Unwrap().OnSuccess(t => - { + }).Unwrap().OnSuccess(t => { // Dirty all objects in memory. - foreach (var obj in uniqueObjects) - { + foreach (var obj in uniqueObjects) { obj.IsDirty = true; } @@ -1080,21 +922,15 @@ string propertyName private static void CollectDirtyChildren(object node, IList dirtyChildren, ICollection seen, - ICollection seenNew) - { - foreach (var obj in DeepTraversal(node).OfType()) - { + ICollection seenNew) { + foreach (var obj in DeepTraversal(node).OfType()) { ICollection scopedSeenNew; // Check for cycles of new objects. Any such cycle means it will be impossible to save // this collection of objects, so throw an exception. - if (obj.ObjectId != null) - { + if (obj.ObjectId != null) { scopedSeenNew = new HashSet(new IdentityEqualityComparer()); - } - else - { - if (seenNew.Contains(obj)) - { + } else { + if (seenNew.Contains(obj)) { throw new InvalidOperationException("Found a circular dependency while saving"); } scopedSeenNew = new HashSet(seenNew, new IdentityEqualityComparer()); @@ -1103,8 +939,7 @@ string propertyName // Check for cycles of any object. If this occurs, then there's no problem, but // we shouldn't recurse any deeper, because it would be an infinite recursion. - if (seen.Contains(obj)) - { + if (seen.Contains(obj)) { return; } seen.Add(obj); @@ -1114,8 +949,7 @@ string propertyName // because that's the only data that might need to be saved now. CollectDirtyChildren(obj.estimatedData, dirtyChildren, seen, scopedSeenNew); - if (obj.CheckIsDirty(false)) - { + if (obj.CheckIsDirty(false)) { dirtyChildren.Add(obj); } } @@ -1125,8 +959,7 @@ string propertyName /// Helper version of CollectDirtyChildren so that callers don't have to add the internally /// used parameters. /// - private static void CollectDirtyChildren(object node, IList dirtyChildren) - { + private static void CollectDirtyChildren(object node, IList dirtyChildren) { CollectDirtyChildren(node, dirtyChildren, new HashSet(new IdentityEqualityComparer()), @@ -1137,23 +970,19 @@ string propertyName /// Returns true if the given object can be serialized for saving as a value /// that is pointed to by a AVObject. /// - private static bool CanBeSerializedAsValue(object value) - { + private static bool CanBeSerializedAsValue(object value) { return DeepTraversal(value, yieldRoot: true) .OfType() .All(o => o.ObjectId != null); } - private bool CanBeSerialized - { - get - { + private bool CanBeSerialized { + get { // This method is only used for batching sets of objects for saveAll // and when saving children automatically. Since it's only used to // determine whether or not save should be called on them, it only // needs to examine their current values, so we use estimatedData. - lock (mutex) - { + lock (mutex) { return CanBeSerializedAsValue(estimatedData); } } @@ -1163,8 +992,7 @@ string propertyName /// Adds a task to the queue for all of the given objects. /// private static Task EnqueueForAll(IEnumerable objects, - Func> taskStart, CancellationToken cancellationToken) - { + Func> taskStart, CancellationToken cancellationToken) { // The task that will be complete when all of the child queues indicate they're ready to start. var readyToStart = new TaskCompletionSource(); @@ -1176,8 +1004,7 @@ string propertyName var lockSet = new LockSet(objects.Select(o => o.taskQueue.Mutex)); lockSet.Enter(); - try - { + try { // The task produced by taskStart. By running this immediately, we allow everything prior // to toAwait to run before waiting for all of the queues on all of the objects. @@ -1185,25 +1012,20 @@ string propertyName // Add fullTask to each of the objects' queues. var childTasks = new List(); - foreach (AVObject obj in objects) - { - obj.taskQueue.Enqueue((Task task) => - { + foreach (AVObject obj in objects) { + obj.taskQueue.Enqueue((Task task) => { childTasks.Add(task); return fullTask; }, cancellationToken); } // When all of the objects' queues are ready, signal fullTask that it's ready to go on. - Task.WhenAll(childTasks.ToArray()).ContinueWith((Task task) => - { + Task.WhenAll(childTasks.ToArray()).ContinueWith((Task task) => { readyToStart.SetResult(null); }); return fullTask; - } - finally - { + } finally { lockSet.Exit(); } } @@ -1212,10 +1034,8 @@ string propertyName /// Removes a key from the object's data if it exists. /// /// The key to remove. - public virtual void Remove(string key) - { - lock (mutex) - { + public virtual void Remove(string key) { + lock (mutex) { CheckKeyIsMutable(key); PerformOperation(key, AVDeleteOperation.Instance); @@ -1225,22 +1045,16 @@ string propertyName private IEnumerable ApplyOperations(IDictionary operations, - IDictionary map) - { + IDictionary map) { List appliedKeys = new List(); - lock (mutex) - { - foreach (var pair in operations) - { + lock (mutex) { + foreach (var pair in operations) { object oldValue; map.TryGetValue(pair.Key, out oldValue); var newValue = pair.Value.Apply(oldValue, pair.Key); - if (newValue != AVDeleteOperation.DeleteToken) - { + if (newValue != AVDeleteOperation.DeleteToken) { map[pair.Key] = newValue; - } - else - { + } else { map.Remove(pair.Key); } appliedKeys.Add(pair.Key); @@ -1252,27 +1066,20 @@ string propertyName /// /// Regenerates the estimatedData map from the serverData and operations. /// - internal void RebuildEstimatedData() - { + internal void RebuildEstimatedData() { IEnumerable changedKeys = null; - lock (mutex) - { + lock (mutex) { //estimatedData.Clear(); List converdKeys = new List(); - foreach (var item in state) - { + foreach (var item in state) { var key = item.Key; var value = item.Value; - if (!estimatedData.ContainsKey(key)) - { + if (!estimatedData.ContainsKey(key)) { converdKeys.Add(key); - } - else - { + } else { var oldValue = estimatedData[key]; - if (oldValue != value) - { + if (oldValue != value) { converdKeys.Add(key); } estimatedData.Remove(key); @@ -1280,8 +1087,7 @@ string propertyName estimatedData.Add(item); } changedKeys = converdKeys; - foreach (var operations in operationSetQueue) - { + foreach (var operations in operationSetQueue) { var appliedKeys = ApplyOperations(operations, estimatedData); changedKeys = converdKeys.Concat(appliedKeys); } @@ -1296,20 +1102,15 @@ string propertyName /// PerformOperation is like setting a value at an index, but instead of /// just taking a new value, it takes a AVFieldOperation that modifies the value. /// - internal void PerformOperation(string key, IAVFieldOperation operation) - { - lock (mutex) - { + internal void PerformOperation(string key, IAVFieldOperation operation) { + lock (mutex) { var ifDirtyBeforePerform = this.IsDirty; object oldValue; estimatedData.TryGetValue(key, out oldValue); object newValue = operation.Apply(oldValue, key); - if (newValue != AVDeleteOperation.DeleteToken) - { + if (newValue != AVDeleteOperation.DeleteToken) { estimatedData[key] = newValue; - } - else - { + } else { estimatedData.Remove(key); } @@ -1318,11 +1119,9 @@ string propertyName CurrentOperations.TryGetValue(key, out oldOperation); var newOperation = operation.MergeWithPrevious(oldOperation); CurrentOperations[key] = newOperation; - if (!wasDirty) - { + if (!wasDirty) { OnPropertyChanged("IsDirty"); - if (ifDirtyBeforePerform != wasDirty) - { + if (ifDirtyBeforePerform != wasDirty) { OnPropertyUpdated("IsDirty", ifDirtyBeforePerform, wasDirty); } } @@ -1336,10 +1135,8 @@ string propertyName /// Override to run validations on key/value pairs. Make sure to still /// call the base version. /// - internal virtual void OnSettingValue(ref string key, ref object value) - { - if (key == null) - { + internal virtual void OnSettingValue(ref string key, ref object value) { + if (key == null) { throw new ArgumentNullException("key"); } } @@ -1353,12 +1150,9 @@ string propertyName /// The property is /// retrieved and is not found. /// The value for the key. - virtual public object this[string key] - { - get - { - lock (mutex) - { + virtual public object this[string key] { + get { + lock (mutex) { CheckGetAccess(key); var value = estimatedData[key]; @@ -1366,18 +1160,15 @@ string propertyName // A relation may be deserialized without a parent or key. Either way, // make sure it's consistent. var relation = value as AVRelationBase; - if (relation != null) - { + if (relation != null) { relation.EnsureParentAndKey(this, key); } return value; } } - set - { - lock (mutex) - { + set { + lock (mutex) { CheckKeyIsMutable(key); Set(key, value); @@ -1390,14 +1181,11 @@ string propertyName /// /// key for the object. /// the value for the key. - internal void Set(string key, object value) - { - lock (mutex) - { + internal void Set(string key, object value) { + lock (mutex) { OnSettingValue(ref key, ref value); - if (!AVEncoder.IsValidType(value)) - { + if (!AVEncoder.IsValidType(value)) { throw new ArgumentException("Invalid type for value: " + value.GetType().ToString()); } @@ -1405,20 +1193,16 @@ string propertyName } } - internal void SetIfDifferent(string key, T value) - { + internal void SetIfDifferent(string key, T value) { T current; bool hasCurrent = TryGetValue(key, out current); - if (value == null) - { - if (hasCurrent) - { + if (value == null) { + if (hasCurrent) { PerformOperation(key, AVDeleteOperation.Instance); } return; } - if (!hasCurrent || !value.Equals(current)) - { + if (!hasCurrent || !value.Equals(current)) { Set(key, value); } } @@ -1429,8 +1213,7 @@ string propertyName /// Atomically increments the given key by 1. /// /// The key to increment. - public void Increment(string key) - { + public void Increment(string key) { Increment(key, 1); } @@ -1439,10 +1222,8 @@ string propertyName /// /// The key to increment. /// The amount to increment by. - public void Increment(string key, long amount) - { - lock (mutex) - { + public void Increment(string key, long amount) { + lock (mutex) { CheckKeyIsMutable(key); PerformOperation(key, new AVIncrementOperation(amount)); @@ -1454,10 +1235,8 @@ string propertyName /// /// The key to increment. /// The amount to increment by. - public void Increment(string key, double amount) - { - lock (mutex) - { + public void Increment(string key, double amount) { + lock (mutex) { CheckKeyIsMutable(key); PerformOperation(key, new AVIncrementOperation(amount)); @@ -1471,8 +1250,7 @@ string propertyName /// /// The key. /// The object to add. - public void AddToList(string key, object value) - { + public void AddToList(string key, object value) { AddRangeToList(key, new[] { value }); } @@ -1481,10 +1259,8 @@ string propertyName /// /// The key. /// The objects to add. - public void AddRangeToList(string key, IEnumerable values) - { - lock (mutex) - { + public void AddRangeToList(string key, IEnumerable values) { + lock (mutex) { CheckKeyIsMutable(key); PerformOperation(key, new AVAddOperation(values.Cast())); @@ -1500,8 +1276,7 @@ string propertyName /// /// The key. /// The object to add. - public void AddUniqueToList(string key, object value) - { + public void AddUniqueToList(string key, object value) { AddRangeUniqueToList(key, new object[] { value }); } @@ -1512,10 +1287,8 @@ string propertyName /// /// The key. /// The objects to add. - public void AddRangeUniqueToList(string key, IEnumerable values) - { - lock (mutex) - { + public void AddRangeUniqueToList(string key, IEnumerable values) { + lock (mutex) { CheckKeyIsMutable(key); PerformOperation(key, new AVAddUniqueOperation(values.Cast())); @@ -1528,10 +1301,8 @@ string propertyName /// /// The key. /// The objects to remove. - public void RemoveAllFromList(string key, IEnumerable values) - { - lock (mutex) - { + public void RemoveAllFromList(string key, IEnumerable values) { + lock (mutex) { CheckKeyIsMutable(key); PerformOperation(key, new AVRemoveOperation(values.Cast())); @@ -1544,10 +1315,8 @@ string propertyName /// Returns whether this object has a particular key. /// /// The key to check for - public bool ContainsKey(string key) - { - lock (mutex) - { + public bool ContainsKey(string key) { + lock (mutex) { return estimatedData.ContainsKey(key); } } @@ -1561,8 +1330,7 @@ string propertyName /// The property is /// retrieved and is not found. /// - public T Get(string key) - { + public T Get(string key) { return Conversion.To(this[key]); } @@ -1572,8 +1340,7 @@ string propertyName /// The type of object to create a relation for. /// The key for the relation field. /// A AVRelation for the key. - public AVRelation GetRelation(string key) where T : AVObject - { + public AVRelation GetRelation(string key) where T : AVObject { // All the sanity checking is done when add or remove is called. AVRelation relation = null; TryGetValue(key, out relation); @@ -1587,14 +1354,11 @@ string propertyName /// parent className /// key /// - public AVQuery GetRelationRevserseQuery(string parentClassName, string key) where T : AVObject - { - if (string.IsNullOrEmpty(parentClassName)) - { + public AVQuery GetRelationRevserseQuery(string parentClassName, string key) where T : AVObject { + if (string.IsNullOrEmpty(parentClassName)) { throw new ArgumentNullException("parentClassName", "can not query a relation without parentClassName."); } - if (string.IsNullOrEmpty(key)) - { + if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key", "can not query a relation without key."); } return new AVQuery(parentClassName).WhereEqualTo(key, this); @@ -1609,20 +1373,14 @@ string propertyName /// requested type, or null if unsuccessful. /// true if the lookup and conversion succeeded, otherwise /// false. - public virtual bool TryGetValue(string key, out T result) - { - lock (mutex) - { - if (ContainsKey(key)) - { - try - { + public virtual bool TryGetValue(string key, out T result) { + lock (mutex) { + if (ContainsKey(key)) { + try { var temp = Conversion.To(this[key]); result = temp; return true; - } - catch (InvalidCastException) - { + } catch (InvalidCastException) { result = default(T); return false; } @@ -1635,48 +1393,37 @@ string propertyName /// /// Gets whether the AVObject has been fetched. /// - public bool IsDataAvailable - { - get - { - lock (mutex) - { + public bool IsDataAvailable { + get { + lock (mutex) { return hasBeenFetched; } } } - private bool CheckIsDataAvailable(string key) - { - lock (mutex) - { + private bool CheckIsDataAvailable(string key) { + lock (mutex) { return IsDataAvailable || estimatedData.ContainsKey(key); } } - private void CheckGetAccess(string key) - { - lock (mutex) - { - if (!CheckIsDataAvailable(key)) - { + private void CheckGetAccess(string key) { + lock (mutex) { + if (!CheckIsDataAvailable(key)) { throw new InvalidOperationException( "AVObject has no data for this key. Call FetchIfNeededAsync() to get the data."); } } } - private void CheckKeyIsMutable(string key) - { - if (!IsKeyMutable(key)) - { + private void CheckKeyIsMutable(string key) { + if (!IsKeyMutable(key)) { throw new InvalidOperationException( "Cannot change the `" + key + "` property of a `" + ClassName + "` object."); } } - protected virtual bool IsKeyMutable(string key) - { + protected virtual bool IsKeyMutable(string key) { return true; } @@ -1684,22 +1431,17 @@ string propertyName /// A helper function for checking whether two AVObjects point to /// the same object in the cloud. /// - public bool HasSameId(AVObject other) - { - lock (mutex) - { + public bool HasSameId(AVObject other) { + lock (mutex) { return other != null && object.Equals(ClassName, other.ClassName) && object.Equals(ObjectId, other.ObjectId); } } - internal IDictionary CurrentOperations - { - get - { - lock (mutex) - { + internal IDictionary CurrentOperations { + get { + lock (mutex) { return operationSetQueue.Last.Value; } } @@ -1709,12 +1451,9 @@ string propertyName /// Gets a set view of the keys contained in this object. This does not include createdAt, /// updatedAt, or objectId. It does include things like username and ACL. /// - public ICollection Keys - { - get - { - lock (mutex) - { + public ICollection Keys { + get { + lock (mutex) { return estimatedData.Keys; } } @@ -1724,8 +1463,7 @@ string propertyName /// Gets or sets the AVACL governing this object. /// [AVFieldName("ACL")] - public AVACL ACL - { + public AVACL ACL { get { return GetProperty(null, "ACL"); } set { SetProperty(value, "ACL"); } } @@ -1740,19 +1478,15 @@ string propertyName #else internal #endif - bool IsNew - { - get - { + bool IsNew { + get { return state.IsNew; } #if !UNITY internal #endif - set - { - MutateState(mutableClone => - { + set { + MutateState(mutableClone => { mutableClone.IsNew = value; }); OnPropertyChanged("IsNew"); @@ -1766,10 +1500,8 @@ string propertyName /// changed locally. /// [AVFieldName("updatedAt")] - public DateTime? UpdatedAt - { - get - { + public DateTime? UpdatedAt { + get { return state.UpdatedAt; } } @@ -1781,10 +1513,8 @@ string propertyName /// the time the object was created locally. /// [AVFieldName("createdAt")] - public DateTime? CreatedAt - { - get - { + public DateTime? CreatedAt { + get { return state.CreatedAt; } } @@ -1792,16 +1522,12 @@ string propertyName /// /// Indicates whether this AVObject has unsaved changes. /// - public bool IsDirty - { - get - { + public bool IsDirty { + get { lock (mutex) { return CheckIsDirty(true); } } - internal set - { - lock (mutex) - { + internal set { + lock (mutex) { dirty = value; OnPropertyChanged("IsDirty"); } @@ -1814,18 +1540,14 @@ string propertyName /// The key to check for. /// true if the key has been altered and not saved yet, otherwise /// false. - public bool IsKeyDirty(string key) - { - lock (mutex) - { + public bool IsKeyDirty(string key) { + lock (mutex) { return CurrentOperations.ContainsKey(key); } } - private bool CheckIsDirty(bool considerChildren) - { - lock (mutex) - { + private bool CheckIsDirty(bool considerChildren) { + lock (mutex) { return (dirty || CurrentOperations.Count > 0 || (considerChildren && HasDirtyChildren)); } } @@ -1836,14 +1558,11 @@ string propertyName /// uniquely identifies an object in your application. /// [AVFieldName("objectId")] - public string ObjectId - { - get - { + public string ObjectId { + get { return state.ObjectId; } - set - { + set { IsDirty = true; SetObjectIdInternal(value); } @@ -1852,12 +1571,9 @@ string propertyName /// Sets the objectId without marking dirty. /// /// The new objectId - private void SetObjectIdInternal(string objectId) - { - lock (mutex) - { - MutateState(mutableClone => - { + private void SetObjectIdInternal(string objectId) { + lock (mutex) { + MutateState(mutableClone => { mutableClone.ObjectId = objectId; }); OnPropertyChanged("ObjectId"); @@ -1867,10 +1583,8 @@ string propertyName /// /// Gets the class name for the AVObject. /// - public string ClassName - { - get - { + public string ClassName { + get { return state.ClassName; } } @@ -1893,12 +1607,9 @@ string propertyName /// /// The key for which a value should be set. /// The value for the key. - public void Add(string key, object value) - { - lock (mutex) - { - if (this.ContainsKey(key)) - { + public void Add(string key, object value) { + lock (mutex) { + if (this.ContainsKey(key)) { throw new ArgumentException("Key already exists", key); } this[key] = value; @@ -1906,18 +1617,14 @@ string propertyName } IEnumerator> IEnumerable> - .GetEnumerator() - { - lock (mutex) - { + .GetEnumerator() { + lock (mutex) { return estimatedData.GetEnumerator(); } } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - lock (mutex) - { + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { + lock (mutex) { return ((IEnumerable>)this).GetEnumerator(); } } @@ -1928,15 +1635,13 @@ string propertyName /// /// The class name of the object. /// A new . - public static AVQuery GetQuery(string className) - { + public static AVQuery GetQuery(string className) { // Since we can't return a AVQuery (due to strong-typing with // generics), we'll require you to go through subclasses. This is a better // experience anyway, especially with LINQ integration, since you'll get // strongly-typed queries and compile-time checking of property names and // types. - if (SubclassingController.GetType(className) != null) - { + if (SubclassingController.GetType(className) != null) { throw new ArgumentException( "Use the class-specific query properties for class " + className, "className"); } @@ -1948,28 +1653,21 @@ string propertyName /// field names. If fieldNames is null, this will notify for all known field-linked /// properties (e.g. this happens when we recalculate all estimated data from scratch) /// - protected virtual void OnFieldsChanged(IEnumerable fieldNames) - { + protected virtual void OnFieldsChanged(IEnumerable fieldNames) { var mappings = SubclassingController.GetPropertyMappings(ClassName); IEnumerable properties; - if (fieldNames != null && mappings != null) - { + if (fieldNames != null && mappings != null) { properties = from m in mappings join f in fieldNames on m.Value equals f select m.Key; - } - else if (mappings != null) - { + } else if (mappings != null) { properties = mappings.Keys; - } - else - { + } else { properties = Enumerable.Empty(); } - foreach (var property in properties) - { + foreach (var property in properties) { OnPropertyChanged(property); } OnPropertyChanged("Item[]"); @@ -1987,8 +1685,7 @@ string propertyName #else string propertyName #endif -) - { +) { propertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); } @@ -1997,14 +1694,11 @@ string propertyName /// /// Occurs when a property value changes. /// - public event PropertyChangedEventHandler PropertyChanged - { - add - { + public event PropertyChangedEventHandler PropertyChanged { + add { propertyChanged.Add(value); } - remove - { + remove { propertyChanged.Remove(value); } } @@ -2012,64 +1706,51 @@ string propertyName private SynchronizedEventHandler propertyUpdated = new SynchronizedEventHandler(); - public event PropertyUpdatedEventHandler PropertyUpdated - { - add - { + public event PropertyUpdatedEventHandler PropertyUpdated { + add { propertyUpdated.Add(value); } - remove - { + remove { propertyUpdated.Remove(value); } } - protected virtual void OnPropertyUpdated(string propertyName, object newValue, object oldValue) - { + protected virtual void OnPropertyUpdated(string propertyName, object newValue, object oldValue) { propertyUpdated.Invoke(this, new PropertyUpdatedEventArgs(propertyName, oldValue, newValue)); } private SynchronizedEventHandler collectionUpdated = new SynchronizedEventHandler(); - public event CollectionPropertyUpdatedEventHandler CollectionPropertyUpdated - { - add - { + public event CollectionPropertyUpdatedEventHandler CollectionPropertyUpdated { + add { collectionUpdated.Add(value); } - remove - { + remove { collectionUpdated.Remove(value); } } - protected virtual void OnCollectionPropertyUpdated(string propertyName, NotifyCollectionUpdatedAction action, IEnumerable oldValues, IEnumerable newValues) - { + protected virtual void OnCollectionPropertyUpdated(string propertyName, NotifyCollectionUpdatedAction action, IEnumerable oldValues, IEnumerable newValues) { collectionUpdated?.Invoke(this, new CollectionPropertyUpdatedEventArgs(propertyName, action, oldValues, newValues)); } } - public interface INotifyPropertyUpdated - { + public interface INotifyPropertyUpdated { event PropertyUpdatedEventHandler PropertyUpdated; } - public interface INotifyCollectionPropertyUpdated - { + public interface INotifyCollectionPropertyUpdated { event CollectionPropertyUpdatedEventHandler CollectionPropertyUpdated; } - public enum NotifyCollectionUpdatedAction - { + public enum NotifyCollectionUpdatedAction { Add, Remove } - public class CollectionPropertyUpdatedEventArgs : PropertyChangedEventArgs - { - public CollectionPropertyUpdatedEventArgs(string propertyName, NotifyCollectionUpdatedAction collectionAction, IEnumerable oldValues, IEnumerable newValues) : base(propertyName) - { + public class CollectionPropertyUpdatedEventArgs : PropertyChangedEventArgs { + public CollectionPropertyUpdatedEventArgs(string propertyName, NotifyCollectionUpdatedAction collectionAction, IEnumerable oldValues, IEnumerable newValues) : base(propertyName) { CollectionAction = collectionAction; OldValues = oldValues; NewValues = newValues; @@ -2082,10 +1763,8 @@ new SynchronizedEventHandler(); public NotifyCollectionUpdatedAction CollectionAction { get; set; } } - public class PropertyUpdatedEventArgs : PropertyChangedEventArgs - { - public PropertyUpdatedEventArgs(string propertyName, object oldValue, object newValue) : base(propertyName) - { + public class PropertyUpdatedEventArgs : PropertyChangedEventArgs { + public PropertyUpdatedEventArgs(string propertyName, object oldValue, object newValue) : base(propertyName) { OldValue = oldValue; NewValue = newValue; } diff --git a/Storage/Storage/Public/AVQuery.cs b/Storage/Storage/Public/AVQuery.cs index c6c676d..748f54a 100644 --- a/Storage/Storage/Public/AVQuery.cs +++ b/Storage/Storage/Public/AVQuery.cs @@ -37,13 +37,13 @@ namespace LeanCloud internal int? skip; internal int? limit; - internal static IAVQueryController QueryController { + internal static AVQueryController QueryController { get { return AVPlugins.Instance.QueryController; } } - internal static IObjectSubclassingController SubclassingController { + internal static ObjectSubclassingController SubclassingController { get { return AVPlugins.Instance.SubclassingController; } diff --git a/Storage/Storage/Public/AVRelation.cs b/Storage/Storage/Public/AVRelation.cs index fa7f13e..faaa46a 100644 --- a/Storage/Storage/Public/AVRelation.cs +++ b/Storage/Storage/Public/AVRelation.cs @@ -31,7 +31,7 @@ namespace LeanCloud this.targetClassName = targetClassName; } - internal static IObjectSubclassingController SubclassingController + internal static ObjectSubclassingController SubclassingController { get { diff --git a/Storage/Storage/Public/AVSession.cs b/Storage/Storage/Public/AVSession.cs index e915b40..0963409 100644 --- a/Storage/Storage/Public/AVSession.cs +++ b/Storage/Storage/Public/AVSession.cs @@ -41,7 +41,7 @@ namespace LeanCloud } } - internal static IAVSessionController SessionController + internal static AVSessionController SessionController { get { diff --git a/Storage/Storage/Public/AVUser.cs b/Storage/Storage/Public/AVUser.cs index 9e2992b..0f89254 100644 --- a/Storage/Storage/Public/AVUser.cs +++ b/Storage/Storage/Public/AVUser.cs @@ -20,7 +20,7 @@ namespace LeanCloud "sessionToken", "isNew" }; - internal static IAVUserController UserController + internal static AVUserController UserController { get { @@ -28,7 +28,7 @@ namespace LeanCloud } } - internal static IAVCurrentUserController CurrentUserController + internal static AVCurrentUserController CurrentUserController { get {