* AWSUploader.cs: chore: await/async

* AVFile.cs:
* AVCloud.cs:
* AVQuery.cs:
* AVLeaderboard.cs:
* QiniuUploader.cs:
* QCloudUploader.cs:
oneRain 2019-09-06 12:24:50 +08:00
parent f3ed814d96
commit aabd25d2e8
7 changed files with 201 additions and 242 deletions

View File

@ -8,15 +8,13 @@ using System.Net.Http.Headers;
namespace LeanCloud.Storage.Internal {
internal class AWSUploader : IFileUploader {
public Task<FileState> Upload(FileState state, Stream dataStream, IDictionary<string, object> fileToken, IProgress<AVUploadProgressEventArgs> progress,
public async Task<FileState> Upload(FileState state, Stream dataStream, IDictionary<string, object> fileToken, IProgress<AVUploadProgressEventArgs> progress,
CancellationToken cancellationToken) {
var uploadUrl = fileToken["upload_url"].ToString();
state.ObjectId = fileToken["objectId"].ToString();
string url = fileToken["url"] as string;
state.Url = new Uri(url, UriKind.Absolute);
return PutFile(state, uploadUrl, dataStream).OnSuccess(s => {
return s.Result;
});
return await PutFile(state, uploadUrl, dataStream);
}
internal async Task<FileState> PutFile(FileState state, string uploadUrl, Stream dataStream) {

View File

@ -19,26 +19,28 @@ namespace LeanCloud.Storage.Internal {
bool done;
private long sliceSize = (long)CommonSize.KB512;
public Task<FileState> Upload(FileState state, Stream dataStream, IDictionary<string, object> fileToken, IProgress<AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) {
public async Task<FileState> Upload(FileState state, Stream dataStream, IDictionary<string, object> fileToken, IProgress<AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) {
fileState = state;
data = dataStream;
uploadUrl = fileToken["upload_url"].ToString();
token = fileToken["token"].ToString();
fileState.ObjectId = fileToken["objectId"].ToString();
bucket = fileToken["bucket"].ToString();
return FileSlice(cancellationToken).OnSuccess(t => {
if (done) return Task<FileState>.FromResult(state);
var response = t.Result.Item2;
var resumeData = response["data"] as IDictionary<string, object>;
if (resumeData.ContainsKey("access_url")) return Task<FileState>.FromResult(state);
var sliceSession = resumeData["session"].ToString();
var sliceOffset = long.Parse(resumeData["offset"].ToString());
return UploadSlice(sliceSession, sliceOffset, dataStream, progress, cancellationToken);
}).Unwrap();
var result = await FileSlice(cancellationToken);
if (done) {
return state;
}
var response = result.Item2;
var resumeData = response["data"] as IDictionary<string, object>;
if (resumeData.ContainsKey("access_url")) {
return state;
}
var sliceSession = resumeData["session"].ToString();
var sliceOffset = long.Parse(resumeData["offset"].ToString());
return await UploadSlice(sliceSession, sliceOffset, dataStream, progress, cancellationToken);
}
Task<FileState> UploadSlice(
async Task<FileState> UploadSlice(
string sessionId,
long offset,
Stream dataStream,
@ -55,21 +57,20 @@ namespace LeanCloud.Storage.Internal {
}
if (offset == dataLength) {
return Task.FromResult<FileState>(fileState);
return fileState;
}
var sliceFile = GetNextBinary(offset, dataStream);
return ExcuteUpload(sessionId, offset, sliceFile, cancellationToken).OnSuccess(_ => {
offset += sliceFile.Length;
if (offset == dataLength) {
done = true;
return Task.FromResult<FileState>(fileState);
}
var response = _.Result.Item2;
var resumeData = response["data"] as IDictionary<string, object>;
var sliceSession = resumeData["session"].ToString();
return UploadSlice(sliceSession, offset, dataStream, progress, cancellationToken);
}).Unwrap();
var result = await ExcuteUpload(sessionId, offset, sliceFile, cancellationToken);
offset += sliceFile.Length;
if (offset == dataLength) {
done = true;
return fileState;
}
var response = result.Item2;
var resumeData = response["data"] as IDictionary<string, object>;
var sliceSession = resumeData["session"].ToString();
return await UploadSlice(sliceSession, offset, dataStream, progress, cancellationToken);
}
Task<Tuple<HttpStatusCode, IDictionary<string, object>>> ExcuteUpload(string sessionId, long offset, byte[] sliceFile, CancellationToken cancellationToken) {
@ -81,19 +82,18 @@ namespace LeanCloud.Storage.Internal {
return PostToQCloud(body, sliceFile, cancellationToken);
}
Task<Tuple<HttpStatusCode, IDictionary<string, object>>> FileSlice(CancellationToken cancellationToken) {
async Task<Tuple<HttpStatusCode, IDictionary<string, object>>> FileSlice(CancellationToken cancellationToken) {
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
var body = new Dictionary<string, object>();
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) {
done = true;
}
return _.Result;
});
var result = await PostToQCloud(body, wholeFile, cancellationToken);
if (result.Item1 == HttpStatusCode.OK) {
done = true;
}
return result;
} else {
body.Add("op", "upload_slice");
body.Add("filesize", data.Length);
@ -101,7 +101,7 @@ namespace LeanCloud.Storage.Internal {
body.Add("slice_size", (long)CommonSize.KB512);
}
return PostToQCloud(body, null, cancellationToken);
return await PostToQCloud(body, null, cancellationToken);
}
public static string HexStringFromBytes(byte[] bytes) {
var sb = new StringBuilder();

View File

@ -22,16 +22,15 @@ namespace LeanCloud.Storage.Internal {
internal static string UP_HOST = "https://up.qbox.me";
private readonly object mutex = new object();
public Task<FileState> Upload(FileState state, Stream dataStream, IDictionary<string, object> fileToken, IProgress<AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) {
public async Task<FileState> Upload(FileState state, Stream dataStream, IDictionary<string, object> fileToken, IProgress<AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) {
state.frozenData = dataStream;
state.CloudName = fileToken["key"] as string;
MergeFromJSON(state, fileToken);
return UploadNextChunk(state, dataStream, string.Empty, 0, progress).OnSuccess(_ => {
return state;
});
await UploadNextChunk(state, dataStream, string.Empty, 0, progress);
return state;
}
Task UploadNextChunk(FileState state, Stream dataStream, string context, long offset, IProgress<AVUploadProgressEventArgs> progress) {
async Task UploadNextChunk(FileState state, Stream dataStream, string context, long offset, IProgress<AVUploadProgressEventArgs> progress) {
var totalSize = dataStream.Length;
var remainingSize = totalSize - state.completed;
@ -43,29 +42,27 @@ namespace LeanCloud.Storage.Internal {
}
}
if (state.completed == totalSize) {
return QiniuMakeFile(state, state.frozenData, state.token, state.CloudName, totalSize, state.block_ctxes.ToArray(), CancellationToken.None);
}
if (state.completed % BLOCKSIZE == 0) {
await QiniuMakeFile(state, state.frozenData, state.token, state.CloudName, totalSize, state.block_ctxes.ToArray(), CancellationToken.None);
} else if (state.completed % BLOCKSIZE == 0) {
var firstChunkBinary = GetChunkBinary(state.completed, dataStream);
var blockSize = remainingSize > BLOCKSIZE ? BLOCKSIZE : remainingSize;
return MakeBlock(state, firstChunkBinary, blockSize).OnSuccess(t => {
var dict = t.Result;
var ctx = dict["ctx"].ToString();
offset = long.Parse(dict["offset"].ToString());
var host = dict["host"].ToString();
var result = await MakeBlock(state, firstChunkBinary, blockSize);
var dict = result;
var ctx = dict["ctx"].ToString();
offset = long.Parse(dict["offset"].ToString());
var host = dict["host"].ToString();
state.completed += firstChunkBinary.Length;
if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) {
state.block_ctxes.Add(ctx);
}
state.completed += firstChunkBinary.Length;
if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) {
state.block_ctxes.Add(ctx);
}
return UploadNextChunk(state, dataStream, ctx, offset, progress);
}).Unwrap();
}
var chunkBinary = GetChunkBinary(state.completed, dataStream);
return PutChunk(state, chunkBinary, context, offset).OnSuccess(t => {
var dict = t.Result;
await UploadNextChunk(state, dataStream, ctx, offset, progress);
} else {
var chunkBinary = GetChunkBinary(state.completed, dataStream);
var result = await PutChunk(state, chunkBinary, context, offset);
var dict = result;
var ctx = dict["ctx"].ToString();
offset = long.Parse(dict["offset"].ToString());
@ -74,9 +71,8 @@ namespace LeanCloud.Storage.Internal {
if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) {
state.block_ctxes.Add(ctx);
}
return UploadNextChunk(state, dataStream, ctx, offset, progress);
}).Unwrap();
await UploadNextChunk(state, dataStream, ctx, offset, progress);
}
}
byte[] GetChunkBinary(long completed, Stream dataStream) {

View File

@ -220,19 +220,18 @@ namespace LeanCloud {
/// <param name="height">captcha image height.</param>
/// <param name="cancellationToken">CancellationToken.</param>
/// <returns>an instance of Captcha.</returns>
public static Task<Captcha> RequestCaptchaAsync(int width = 85, int height = 30, CancellationToken cancellationToken = default) {
public static async Task<Captcha> RequestCaptchaAsync(int width = 85, int height = 30, CancellationToken cancellationToken = default) {
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<IDictionary<string, object>>(command, cancellationToken).OnSuccess(t => {
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
return new Captcha() {
Token = decoded["captcha_token"] as string,
Url = decoded["captcha_url"] as string,
};
});
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
var decoded = AVDecoder.Instance.Decode(result.Item2) as IDictionary<string, object>;
return new Captcha {
Token = decoded["captcha_token"] as string,
Url = decoded["captcha_url"] as string,
};
}
/// <summary>
@ -242,7 +241,7 @@ namespace LeanCloud {
/// <param name="code">User's input of this captcha.</param>
/// <param name="cancellationToken">CancellationToken.</param>
/// <returns></returns>
public static Task<string> VerifyCaptchaAsync(string code, string token, CancellationToken cancellationToken = default) {
public static async Task<string> VerifyCaptchaAsync(string code, string token, CancellationToken cancellationToken = default) {
var data = new Dictionary<string, object> {
{ "captcha_token", token },
{ "captcha_code", code },
@ -252,11 +251,11 @@ namespace LeanCloud {
Method = HttpMethod.Post,
Content = data
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken).ContinueWith(t => {
if (!t.Result.Item2.ContainsKey("validate_token"))
throw new KeyNotFoundException("validate_token");
return t.Result.Item2["validate_token"] as string;
});
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
if (result.Item2.TryGetValue("validate_token", out object tokenObj)) {
return tokenObj as string;
}
throw new KeyNotFoundException("validate_token");
}
/// <summary>
@ -264,16 +263,15 @@ namespace LeanCloud {
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static Task<IDictionary<string, object>> GetCustomParametersAsync(CancellationToken cancellationToken = default) {
public static async Task<IDictionary<string, object>> GetCustomParametersAsync(CancellationToken cancellationToken = default) {
var command = new AVCommand {
Path = $"statistics/apps/{AVClient.CurrentConfiguration.ApplicationId}/sendPolicy",
Method = HttpMethod.Get
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken).OnSuccess(t => {
var settings = t.Result.Item2;
var CloudParameters = settings["parameters"] as IDictionary<string, object>;
return CloudParameters;
});
var data = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
var settings = data.Item2;
var CloudParameters = settings["parameters"] as IDictionary<string, object>;
return CloudParameters;
}
public class RealtimeSignature {
@ -283,7 +281,7 @@ namespace LeanCloud {
public string Signature { internal set; get; }
}
public static Task<RealtimeSignature> RequestRealtimeSignatureAsync(CancellationToken cancellationToken = default) {
public static async Task<RealtimeSignature> RequestRealtimeSignatureAsync(CancellationToken cancellationToken = default) {
var command = new AVCommand {
Path = "rtm/sign",
Method = HttpMethod.Post,
@ -291,15 +289,14 @@ namespace LeanCloud {
{ "session_token", AVUser.CurrentUser?.SessionToken }
}
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken).OnSuccess(t => {
var body = t.Result.Item2;
return new RealtimeSignature() {
Nonce = body["nonce"] as string,
Timestamp = (long)body["timestamp"],
ClientId = body["client_id"] as string,
Signature = body["signature"] as string,
};
});
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
var body = result.Item2;
return new RealtimeSignature() {
Nonce = body["nonce"] as string,
Timestamp = (long)body["timestamp"],
ClientId = body["client_id"] as string,
Signature = body["signature"] as string,
};
}
/// <summary>

View File

@ -265,11 +265,8 @@ namespace LeanCloud {
/// </summary>
/// <param name="progress">The progress callback.</param>
/// <param name="cancellationToken">The cancellation token.</param>
public Task SaveAsync(IProgress<AVUploadProgressEventArgs> progress = null, CancellationToken cancellationToken = default) {
return FileController.SaveAsync(state, dataStream, progress, cancellationToken)
.OnSuccess(t => {
state = t.Result;
});
public async Task SaveAsync(IProgress<AVUploadProgressEventArgs> progress = null, CancellationToken cancellationToken = default) {
state = await FileController.SaveAsync(state, dataStream, progress, cancellationToken);
}
#endregion
@ -320,11 +317,9 @@ namespace LeanCloud {
/// </summary>
/// <remarks>获取之后并没有实际执行下载只是加载了文件的元信息以及物理地址Url
/// </remarks>
public static Task<AVFile> GetFileWithObjectIdAsync(string objectId, CancellationToken cancellationToken = default) {
return FileController.GetAsync(objectId, cancellationToken).OnSuccess(_ => {
var filestate = _.Result;
return new AVFile(filestate);
});
public static async Task<AVFile> GetFileWithObjectIdAsync(string objectId, CancellationToken cancellationToken = default) {
var fileState = await FileController.GetAsync(objectId, cancellationToken);
return new AVFile(fileState);
}
public static AVFile CreateWithoutData(string objectId) {

View File

@ -10,8 +10,7 @@ using System.Text.RegularExpressions;
using Newtonsoft.Json;
using LeanCloud.Storage.Internal;
namespace LeanCloud
{
namespace LeanCloud {
public class AVQuery<T> where T : AVObject {
public string ClassName {
get; internal set;
@ -24,7 +23,8 @@ namespace LeanCloud
return $"classes/{Uri.EscapeDataString(ClassName)}";
}
return path;
} set {
}
set {
path = value;
}
}
@ -202,56 +202,41 @@ namespace LeanCloud
});
}
public Task<IEnumerable<T>> FindAsync(CancellationToken cancellationToken = default)
{
return QueryController.FindAsync<T>(this, AVUser.CurrentUser, cancellationToken).OnSuccess(t => {
IEnumerable<IObjectState> states = t.Result;
return (from state in states
select AVObject.FromState<T>(state, ClassName));
});
public async Task<IEnumerable<T>> FindAsync(CancellationToken cancellationToken = default) {
IEnumerable<IObjectState> states = await QueryController.FindAsync(this, AVUser.CurrentUser, cancellationToken);
return (from state in states
select AVObject.FromState<T>(state, ClassName));
}
public Task<T> FirstOrDefaultAsync(CancellationToken cancellationToken = default)
{
return QueryController.FirstAsync<T>(this, AVUser.CurrentUser, cancellationToken).OnSuccess(t => {
IObjectState state = t.Result;
return state == null ? default : AVObject.FromState<T>(state, ClassName);
});
public async Task<T> FirstOrDefaultAsync(CancellationToken cancellationToken = default) {
IObjectState state = await QueryController.FirstAsync<T>(this, AVUser.CurrentUser, cancellationToken);
return state == null ? default : AVObject.FromState<T>(state, ClassName);
}
public Task<T> FirstAsync(CancellationToken cancellationToken = default)
{
return FirstOrDefaultAsync(cancellationToken).OnSuccess(t =>
{
if (t.Result == null)
{
throw new AVException(AVException.ErrorCode.ObjectNotFound,
"No results matched the query.");
}
return t.Result;
});
public async Task<T> FirstAsync(CancellationToken cancellationToken = default) {
var result = await FirstOrDefaultAsync(cancellationToken);
if (result == null) {
throw new AVException(AVException.ErrorCode.ObjectNotFound,
"No results matched the query.");
}
return result;
}
public Task<int> CountAsync(CancellationToken cancellationToken = default)
{
public Task<int> CountAsync(CancellationToken cancellationToken = default) {
return QueryController.CountAsync(this, AVUser.CurrentUser, cancellationToken);
}
public Task<T> GetAsync(string objectId, CancellationToken cancellationToken)
{
public async Task<T> GetAsync(string objectId, CancellationToken cancellationToken) {
AVQuery<T> singleItemQuery = new AVQuery<T>(ClassName)
.WhereEqualTo("objectId", objectId);
singleItemQuery = new AVQuery<T>(singleItemQuery, includes: this.includes, selectedKeys: this.selectedKeys, limit: 1);
return singleItemQuery.FindAsync(cancellationToken).OnSuccess(t =>
{
var result = t.Result.FirstOrDefault();
if (result == null)
{
throw new AVException(AVException.ErrorCode.ObjectNotFound,
"Object with the given objectId not found.");
}
return result;
});
var result = await singleItemQuery.FindAsync(cancellationToken);
var first = result.FirstOrDefault();
if (first == null) {
throw new AVException(AVException.ErrorCode.ObjectNotFound,
"Object with the given objectId not found.");
}
return first;
}
#region CQL
@ -289,22 +274,20 @@ namespace LeanCloud
return RebuildObjectFromCloudQueryResult(queryString);
}
internal static Task<IEnumerable<T>> RebuildObjectFromCloudQueryResult(string queryString) {
internal static async Task<IEnumerable<T>> RebuildObjectFromCloudQueryResult(string queryString) {
var command = new AVCommand {
Path = queryString,
Method = HttpMethod.Get
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: CancellationToken.None).OnSuccess(t =>
{
var items = t.Result.Item2["results"] as IList<object>;
var className = t.Result.Item2["className"].ToString();
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, CancellationToken.None);
var items = result.Item2["results"] as IList<object>;
var className = result.Item2["className"].ToString();
IEnumerable<IObjectState> states = (from item in items
select AVObjectCoder.Instance.Decode(item as IDictionary<string, object>, AVDecoder.Instance));
IEnumerable<IObjectState> states = (from item in items
select AVObjectCoder.Instance.Decode(item as IDictionary<string, object>, AVDecoder.Instance));
return (from state in states
select AVObject.FromState<T>(state, className));
});
return from state in states
select AVObject.FromState<T>(state, className);
}
#endregion

View File

@ -138,7 +138,7 @@ namespace LeanCloud {
/// <param name="order">排序方式</param>
/// <param name="versionChangeInterval">版本更新频率</param>
/// <param name="updateStrategy">成绩更新策略</param>
public static Task<AVLeaderboard> CreateLeaderboard(string statisticName,
public static async Task<AVLeaderboard> CreateLeaderboard(string statisticName,
AVLeaderboardOrder order = AVLeaderboardOrder.DESCENDING,
AVLeaderboardUpdateStrategy updateStrategy = AVLeaderboardUpdateStrategy.BETTER,
AVLeaderboardVersionChangeInterval versionChangeInterval = AVLeaderboardVersionChangeInterval.WEEK) {
@ -157,14 +157,13 @@ namespace LeanCloud {
Method = HttpMethod.Post,
Content = data
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
try {
var leaderboard = Parse(t.Result.Item2);
return leaderboard;
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
}
});
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
try {
var leaderboard = Parse(result.Item2);
return leaderboard;
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
}
}
/// <summary>
@ -195,7 +194,7 @@ namespace LeanCloud {
/// <param name="user">用户</param>
/// <param name="statistics">成绩</param>
/// <param name="overwrite">是否强行覆盖</param>
public static Task<List<AVStatistic>> UpdateStatistics(AVUser user, Dictionary<string, double> statistics, bool overwrite = false) {
public static async Task<List<AVStatistic>> UpdateStatistics(AVUser user, Dictionary<string, double> statistics, bool overwrite = false) {
if (user == null) {
throw new ArgumentNullException(nameof(user));
}
@ -219,18 +218,17 @@ namespace LeanCloud {
Method = HttpMethod.Post,
Content = data
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
try {
List<AVStatistic> statisticList = new List<AVStatistic>();
List<object> list = t.Result.Item2["results"] as List<object>;
foreach (object obj in list) {
statisticList.Add(AVStatistic.Parse(obj as IDictionary<string, object>));
}
return statisticList;
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
try {
List<AVStatistic> statisticList = new List<AVStatistic>();
List<object> list = result.Item2["results"] as List<object>;
foreach (object obj in list) {
statisticList.Add(AVStatistic.Parse(obj as IDictionary<string, object>));
}
});
return statisticList;
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
}
}
/// <summary>
@ -239,7 +237,7 @@ namespace LeanCloud {
/// <returns>成绩列表</returns>
/// <param name="user">用户</param>
/// <param name="statisticNames">名称列表</param>
public static Task<List<AVStatistic>> GetStatistics(AVUser user, List<string> statisticNames = null) {
public static async Task<List<AVStatistic>> GetStatistics(AVUser user, List<string> statisticNames = null) {
if (user == null) {
throw new ArgumentNullException(nameof(user));
}
@ -252,18 +250,17 @@ namespace LeanCloud {
Path = path,
Method = HttpMethod.Post
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
try {
List<AVStatistic> statisticList = new List<AVStatistic>();
List<object> list = t.Result.Item2["results"] as List<object>;
foreach (object obj in list) {
statisticList.Add(AVStatistic.Parse(obj as IDictionary<string, object>));
}
return statisticList;
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
try {
List<AVStatistic> statisticList = new List<AVStatistic>();
List<object> list = result.Item2["results"] as List<object>;
foreach (object obj in list) {
statisticList.Add(AVStatistic.Parse(obj as IDictionary<string, object>));
}
});
return statisticList;
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
}
}
/// <summary>
@ -271,7 +268,7 @@ namespace LeanCloud {
/// </summary>
/// <param name="user">用户</param>
/// <param name="statisticNames">名称列表</param>
public static Task DeleteStatistics(AVUser user, List<string> statisticNames) {
public static async Task DeleteStatistics(AVUser user, List<string> statisticNames) {
if (user == null) {
throw new ArgumentNullException(nameof(user));
}
@ -285,7 +282,7 @@ namespace LeanCloud {
Path = path,
Method = HttpMethod.Delete,
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
}
/// <summary>
@ -294,21 +291,20 @@ namespace LeanCloud {
/// <returns>排行榜归档列表</returns>
/// <param name="skip">跳过数量</param>
/// <param name="limit">分页数量</param>
public Task<List<AVLeaderboardArchive>> GetArchives(int skip = 0, int limit = 10) {
public async Task<List<AVLeaderboardArchive>> GetArchives(int skip = 0, int limit = 10) {
var path = string.Format("leaderboard/leaderboards/{0}/archives", StatisticName);
path = string.Format("{0}?skip={1}&limit={2}", path, skip, limit);
var command = new AVCommand {
Path = path,
Method = HttpMethod.Get
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
List<AVLeaderboardArchive> archives = new List<AVLeaderboardArchive>();
List<object> list = t.Result.Item2["results"] as List<object>;
foreach (object obj in list) {
archives.Add(AVLeaderboardArchive.Parse(obj as IDictionary<string, object>));
}
return archives;
});
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
List<AVLeaderboardArchive> archives = new List<AVLeaderboardArchive>();
List<object> list = result.Item2["results"] as List<object>;
foreach (object obj in list) {
archives.Add(AVLeaderboardArchive.Parse(obj as IDictionary<string, object>));
}
return archives;
}
/// <summary>
@ -336,7 +332,7 @@ namespace LeanCloud {
return GetResults(AVUser.CurrentUser, version, skip, limit, selectUserKeys, includeStatistics);
}
Task<List<AVRanking>> GetResults(AVUser user,
async Task<List<AVRanking>> GetResults(AVUser user,
int version, int skip, int limit,
List<string> selectUserKeys,
List<string> includeStatistics) {
@ -361,18 +357,17 @@ namespace LeanCloud {
Path = path,
Method = HttpMethod.Get
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
try {
List<AVRanking> rankingList = new List<AVRanking>();
List<object> list = t.Result.Item2["results"] as List<object>;
foreach (object obj in list) {
rankingList.Add(AVRanking.Parse(obj as IDictionary<string, object>));
}
return rankingList;
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
try {
List<AVRanking> rankingList = new List<AVRanking>();
List<object> list = result.Item2["results"] as List<object>;
foreach (object obj in list) {
rankingList.Add(AVRanking.Parse(obj as IDictionary<string, object>));
}
});
return rankingList;
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
}
}
/// <summary>
@ -380,14 +375,13 @@ namespace LeanCloud {
/// </summary>
/// <returns>排行榜对象</returns>
/// <param name="updateStrategy">更新策略</param>
public Task<AVLeaderboard> UpdateUpdateStrategy(AVLeaderboardUpdateStrategy updateStrategy) {
public async Task<AVLeaderboard> UpdateUpdateStrategy(AVLeaderboardUpdateStrategy updateStrategy) {
var data = new Dictionary<string, object> {
{ "updateStrategy", updateStrategy.ToString().ToLower() }
};
return Update(data).OnSuccess(t => {
UpdateStrategy = (AVLeaderboardUpdateStrategy)Enum.Parse(typeof(AVLeaderboardUpdateStrategy), t.Result["updateStrategy"].ToString().ToUpper());
return this;
});
var result = await Update(data);
UpdateStrategy = (AVLeaderboardUpdateStrategy)Enum.Parse(typeof(AVLeaderboardUpdateStrategy), result["updateStrategy"].ToString().ToUpper());
return this;
}
/// <summary>
@ -395,67 +389,63 @@ namespace LeanCloud {
/// </summary>
/// <returns>排行榜对象</returns>
/// <param name="versionChangeInterval">版本更新频率</param>
public Task<AVLeaderboard> UpdateVersionChangeInterval(AVLeaderboardVersionChangeInterval versionChangeInterval) {
public async Task<AVLeaderboard> UpdateVersionChangeInterval(AVLeaderboardVersionChangeInterval versionChangeInterval) {
var data = new Dictionary<string, object> {
{ "versionChangeInterval", versionChangeInterval.ToString().ToLower() }
};
return Update(data).OnSuccess(t => {
VersionChangeInterval = (AVLeaderboardVersionChangeInterval)Enum.Parse(typeof(AVLeaderboardVersionChangeInterval), t.Result["versionChangeInterval"].ToString().ToUpper());
return this;
});
var result = await Update(data);
VersionChangeInterval = (AVLeaderboardVersionChangeInterval)Enum.Parse(typeof(AVLeaderboardVersionChangeInterval), result["versionChangeInterval"].ToString().ToUpper());
return this;
}
Task<IDictionary<string,object>> Update(Dictionary<string, object> data) {
async Task<IDictionary<string,object>> Update(Dictionary<string, object> data) {
var path = string.Format("leaderboard/leaderboards/{0}", StatisticName);
var command = new AVCommand {
Path = path,
Method = HttpMethod.Put,
Content = data
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
return t.Result.Item2;
});
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
return result.Item2;
}
/// <summary>
/// 拉取排行榜数据
/// </summary>
/// <returns>排行榜对象</returns>
public Task<AVLeaderboard> Fetch() {
public async Task<AVLeaderboard> Fetch() {
var path = string.Format("leaderboard/leaderboards/{0}", StatisticName);
var command = new AVCommand {
Path = path,
Method = HttpMethod.Get
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
try {
// 反序列化 Leaderboard 对象
var leaderboard = Parse(t.Result.Item2);
return leaderboard;
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
}
});
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
try {
// 反序列化 Leaderboard 对象
var leaderboard = Parse(result.Item2);
return leaderboard;
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
}
}
/// <summary>
/// 重置排行榜
/// </summary>
/// <returns>排行榜对象</returns>
public Task<AVLeaderboard> Reset() {
public async Task<AVLeaderboard> Reset() {
var path = string.Format("leaderboard/leaderboards/{0}/incrementVersion", StatisticName);
var command = new AVCommand {
Path = path,
Method = HttpMethod.Put
};
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
try {
Init(t.Result.Item2);
return this;
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
}
});
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
try {
Init(result.Item2);
return this;
} catch (Exception e) {
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
}
}
/// <summary>