* AVLiveQuery.cs: chore: 支持 Object Fetch

* AVFile.cs:
* AVCloud.cs:
* AVObject.cs:
* AVExtensions.cs:
* ObjectControllerTests.cs:
oneRain 2019-08-28 11:07:12 +08:00
parent 548d2314a1
commit 9d3c9dc178
6 changed files with 52 additions and 63 deletions

View File

@ -179,7 +179,7 @@ namespace LeanCloud.LiveQuery
{ "id", AVLiveQuery.InstallationId }, { "id", AVLiveQuery.InstallationId },
{ "clientTimestamp", AVLiveQuery.ClientTs } { "clientTimestamp", AVLiveQuery.ClientTs }
}; };
string sessionToken = AVUser.CurrentUser != null ? AVUser.CurrentUser.SessionToken : string.Empty; string sessionToken = AVUser.CurrentUser?.SessionToken;
if (!string.IsNullOrEmpty(sessionToken)) { if (!string.IsNullOrEmpty(sessionToken)) {
data.Add("sessionToken", sessionToken); data.Add("sessionToken", sessionToken);
} }
@ -200,7 +200,7 @@ namespace LeanCloud.LiveQuery
{ "id", AVLiveQuery.InstallationId }, { "id", AVLiveQuery.InstallationId },
{ "query_id", Id }, { "query_id", Id },
}; };
string sessionToken = AVUser.CurrentUser != null ? AVUser.CurrentUser.SessionToken : string.Empty; string sessionToken = AVUser.CurrentUser?.SessionToken;
var command = new AVCommand("LiveQuery/unsubscribe", var command = new AVCommand("LiveQuery/unsubscribe",
"POST", "POST",
sessionToken, sessionToken,

View File

@ -1,6 +1,7 @@
using NUnit.Framework; using NUnit.Framework;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Generic;
using LeanCloud; using LeanCloud;
namespace LeanCloudTests { namespace LeanCloudTests {
@ -11,9 +12,9 @@ namespace LeanCloudTests {
} }
[Test] [Test]
public async Task TestSave() { public async Task Save() {
TestContext.Out.WriteLine($"before at {Thread.CurrentThread.ManagedThreadId}"); TestContext.Out.WriteLine($"before at {Thread.CurrentThread.ManagedThreadId}");
var obj = AVObject.Create("Foo"); AVObject obj = AVObject.Create("Foo");
obj["content"] = "hello, world"; obj["content"] = "hello, world";
await obj.SaveAsync(); await obj.SaveAsync();
TestContext.Out.WriteLine($"{obj.ObjectId} saved at {Thread.CurrentThread.ManagedThreadId}"); TestContext.Out.WriteLine($"{obj.ObjectId} saved at {Thread.CurrentThread.ManagedThreadId}");
@ -23,12 +24,27 @@ namespace LeanCloudTests {
} }
[Test] [Test]
public async Task ObjectFetch() { public async Task Fetch() {
AVObject obj = AVObject.CreateWithoutData("Todo", "5d5f6039d5de2b006cf29c8f"); AVObject obj = AVObject.CreateWithoutData("Todo", "5d5f6039d5de2b006cf29c8f");
await obj.FetchAsync(); await obj.FetchAsync();
Assert.NotNull(obj["title"]); Assert.NotNull(obj["title"]);
Assert.NotNull(obj["content"]); Assert.NotNull(obj["content"]);
TestContext.Out.WriteLine($"{obj["title"]}, {obj["content"]}"); TestContext.Out.WriteLine($"{obj["title"]}, {obj["content"]}");
} }
[Test]
public async Task FetchWithKeys() {
AVObject obj = AVObject.CreateWithoutData("Post", "5d3abfa530863b0068e1b326");
await obj.FetchAsync(new List<string> { "pubUser" });
TestContext.Out.WriteLine($"{obj["pubUser"]}");
}
[Test]
public async Task FetchWithIncludes() {
AVObject obj = AVObject.CreateWithoutData("Post", "5d3abfa530863b0068e1b326");
await obj.FetchAsync(includes: new List<string> { "tag" });
AVObject tag = obj["tag"] as AVObject;
TestContext.Out.WriteLine($"{tag["name"]}");
}
} }
} }

View File

@ -43,7 +43,7 @@ namespace LeanCloud {
/// <returns>The result of the cloud call.</returns> /// <returns>The result of the cloud call.</returns>
public static Task<T> CallFunctionAsync<T>(String name, IDictionary<string, object> parameters = null, string sesstionToken = null, CancellationToken cancellationToken = default(CancellationToken)) { public static Task<T> CallFunctionAsync<T>(String name, IDictionary<string, object> parameters = null, string sesstionToken = null, CancellationToken cancellationToken = default(CancellationToken)) {
return CloudCodeController.CallFunctionAsync<T>(name, return CloudCodeController.CallFunctionAsync<T>(name,
parameters, AVUser.CurrentUser.SessionToken, parameters, AVUser.CurrentUser?.SessionToken,
cancellationToken); cancellationToken);
} }
@ -58,7 +58,7 @@ namespace LeanCloud {
/// <returns></returns> /// <returns></returns>
public static Task<T> RPCFunctionAsync<T>(String name, IDictionary<string, object> parameters = null, string sesstionToken = null, CancellationToken cancellationToken = default(CancellationToken)) { public static Task<T> RPCFunctionAsync<T>(String name, IDictionary<string, object> parameters = null, string sesstionToken = null, CancellationToken cancellationToken = default(CancellationToken)) {
return CloudCodeController.RPCFunction<T>(name, return CloudCodeController.RPCFunction<T>(name,
parameters, AVUser.CurrentUser.SessionToken, parameters, AVUser.CurrentUser?.SessionToken,
cancellationToken); cancellationToken);
} }

View File

@ -1,24 +1,22 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq; using System.Linq;
using LeanCloud.Storage.Internal; using LeanCloud.Storage.Internal;
namespace LeanCloud namespace LeanCloud {
{
/// <summary> /// <summary>
/// Provides convenience extension methods for working with collections /// Provides convenience extension methods for working with collections
/// of AVObjects so that you can easily save and fetch them in batches. /// of AVObjects so that you can easily save and fetch them in batches.
/// </summary> /// </summary>
public static class AVExtensions public static class AVExtensions {
{
/// <summary> /// <summary>
/// Saves all of the AVObjects in the enumeration. Equivalent to /// Saves all of the AVObjects in the enumeration. Equivalent to
/// calling <see cref="AVObject.SaveAllAsync{T}(IEnumerable{T})"/>. /// calling <see cref="AVObject.SaveAllAsync{T}(IEnumerable{T})"/>.
/// </summary> /// </summary>
/// <param name="objects">The objects to save.</param> /// <param name="objects">The objects to save.</param>
public static Task SaveAllAsync<T>(this IEnumerable<T> objects) where T : AVObject public static Task SaveAllAsync<T>(this IEnumerable<T> objects) where T : AVObject {
{
return AVObject.SaveAllAsync(objects); return AVObject.SaveAllAsync(objects);
} }
@ -30,8 +28,7 @@ namespace LeanCloud
/// <param name="objects">The objects to save.</param> /// <param name="objects">The objects to save.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
public static Task SaveAllAsync<T>( public static Task SaveAllAsync<T>(
this IEnumerable<T> objects, CancellationToken cancellationToken) where T : AVObject this IEnumerable<T> objects, CancellationToken cancellationToken) where T : AVObject {
{
return AVObject.SaveAllAsync(objects, cancellationToken); return AVObject.SaveAllAsync(objects, cancellationToken);
} }
@ -41,8 +38,7 @@ namespace LeanCloud
/// </summary> /// </summary>
/// <param name="objects">The objects to save.</param> /// <param name="objects">The objects to save.</param>
public static Task<IEnumerable<T>> FetchAllAsync<T>(this IEnumerable<T> objects) public static Task<IEnumerable<T>> FetchAllAsync<T>(this IEnumerable<T> objects)
where T : AVObject where T : AVObject {
{
return AVObject.FetchAllAsync(objects); return AVObject.FetchAllAsync(objects);
} }
@ -55,8 +51,7 @@ namespace LeanCloud
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
public static Task<IEnumerable<T>> FetchAllAsync<T>( public static Task<IEnumerable<T>> FetchAllAsync<T>(
this IEnumerable<T> objects, CancellationToken cancellationToken) this IEnumerable<T> objects, CancellationToken cancellationToken)
where T : AVObject where T : AVObject {
{
return AVObject.FetchAllAsync(objects, cancellationToken); return AVObject.FetchAllAsync(objects, cancellationToken);
} }
@ -68,8 +63,7 @@ namespace LeanCloud
/// <param name="objects">The objects to fetch.</param> /// <param name="objects">The objects to fetch.</param>
public static Task<IEnumerable<T>> FetchAllIfNeededAsync<T>( public static Task<IEnumerable<T>> FetchAllIfNeededAsync<T>(
this IEnumerable<T> objects) this IEnumerable<T> objects)
where T : AVObject where T : AVObject {
{
return AVObject.FetchAllIfNeededAsync(objects); return AVObject.FetchAllIfNeededAsync(objects);
} }
@ -82,8 +76,7 @@ namespace LeanCloud
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
public static Task<IEnumerable<T>> FetchAllIfNeededAsync<T>( public static Task<IEnumerable<T>> FetchAllIfNeededAsync<T>(
this IEnumerable<T> objects, CancellationToken cancellationToken) this IEnumerable<T> objects, CancellationToken cancellationToken)
where T : AVObject where T : AVObject {
{
return AVObject.FetchAllIfNeededAsync(objects, cancellationToken); return AVObject.FetchAllIfNeededAsync(objects, cancellationToken);
} }
@ -95,43 +88,25 @@ namespace LeanCloud
/// <param name="queries">The list of AVQueries to 'or' together.</param> /// <param name="queries">The list of AVQueries to 'or' together.</param>
/// <returns>A query that is the or of the given queries.</returns> /// <returns>A query that is the or of the given queries.</returns>
public static AVQuery<T> Or<T>(this AVQuery<T> source, params AVQuery<T>[] queries) public static AVQuery<T> Or<T>(this AVQuery<T> source, params AVQuery<T>[] queries)
where T : AVObject where T : AVObject {
{
return AVQuery<T>.Or(queries.Concat(new[] { source })); return AVQuery<T>.Or(queries.Concat(new[] { source }));
} }
/// <summary> public static Task<T> FetchAsync<T>(this T obj,
/// Fetches this object with the data from the server. IEnumerable<string> keys = null, IEnumerable<string> includes = null, AVACL includeACL = null,
/// </summary> CancellationToken cancellationToken = default) where T : AVObject {
public static Task<T> FetchAsync<T>(this T obj) where T : AVObject
{
return obj.FetchAsyncInternal(CancellationToken.None).OnSuccess(t => (T)t.Result);
}
/// <summary>
/// Fetches this object with the data from the server.
/// </summary>
/// <param name="obj">The AVObject to fetch.</param>
/// <param name="cancellationToken">The cancellation token.</param>
public static Task<T> FetchAsync<T>(this T obj, CancellationToken cancellationToken)
where T : AVObject
{
return FetchAsync<T>(obj, null, cancellationToken);
}
public static Task<T> FetchAsync<T>(this T obj, IEnumerable<string> includeKeys) where T : AVObject
{
return FetchAsync<T>(obj, includeKeys, CancellationToken.None).OnSuccess(t => (T)t.Result);
}
public static Task<T> FetchAsync<T>(this T obj, IEnumerable<string> includeKeys, CancellationToken cancellationToken)
where T : AVObject
{
var queryString = new Dictionary<string, object>(); var queryString = new Dictionary<string, object>();
if (includeKeys != null) if (keys != null) {
{ var encode = String.Join(",", keys.ToArray());
queryString.Add("keys", encode);
var encode = string.Join(",", includeKeys.ToArray()); }
if (includes != null) {
var encode = String.Join(",", includes.ToArray());
queryString.Add("include", encode); queryString.Add("include", encode);
} }
if (includeACL != null) {
queryString.Add("returnACL", includeACL);
}
return obj.FetchAsyncInternal(queryString, cancellationToken).OnSuccess(t => (T)t.Result); return obj.FetchAsyncInternal(queryString, cancellationToken).OnSuccess(t => (T)t.Result);
} }
@ -140,8 +115,7 @@ namespace LeanCloud
/// false), fetches this object with the data from the server. /// false), fetches this object with the data from the server.
/// </summary> /// </summary>
/// <param name="obj">The AVObject to fetch.</param> /// <param name="obj">The AVObject to fetch.</param>
public static Task<T> FetchIfNeededAsync<T>(this T obj) where T : AVObject public static Task<T> FetchIfNeededAsync<T>(this T obj) where T : AVObject {
{
return obj.FetchIfNeededAsyncInternal(CancellationToken.None).OnSuccess(t => (T)t.Result); return obj.FetchIfNeededAsyncInternal(CancellationToken.None).OnSuccess(t => (T)t.Result);
} }
@ -152,8 +126,7 @@ namespace LeanCloud
/// <param name="obj">The AVObject to fetch.</param> /// <param name="obj">The AVObject to fetch.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
public static Task<T> FetchIfNeededAsync<T>(this T obj, CancellationToken cancellationToken) public static Task<T> FetchIfNeededAsync<T>(this T obj, CancellationToken cancellationToken)
where T : AVObject where T : AVObject {
{
return obj.FetchIfNeededAsyncInternal(cancellationToken).OnSuccess(t => (T)t.Result); return obj.FetchIfNeededAsyncInternal(cancellationToken).OnSuccess(t => (T)t.Result);
} }
} }

View File

@ -656,7 +656,7 @@ namespace LeanCloud {
return Task.FromResult(0); return Task.FromResult(0);
} }
string sessionToken = AVUser.CurrentUser.SessionToken; string sessionToken = AVUser.CurrentUser?.SessionToken;
return toAwait.OnSuccess(_ => { return toAwait.OnSuccess(_ => {
return FileController.DeleteAsync(state, sessionToken, cancellationToken); return FileController.DeleteAsync(state, sessionToken, cancellationToken);

View File

@ -709,7 +709,7 @@ string propertyName
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
public static Task SaveAllAsync<T>( public static Task SaveAllAsync<T>(
IEnumerable<T> objects, CancellationToken cancellationToken) where T : AVObject { IEnumerable<T> objects, CancellationToken cancellationToken) where T : AVObject {
return DeepSaveAsync(objects.ToList(), AVUser.CurrentUser.SessionToken, cancellationToken); return DeepSaveAsync(objects.ToList(), AVUser.CurrentUser?.SessionToken, cancellationToken);
} }
#endregion #endregion
@ -857,7 +857,7 @@ string propertyName
return Task.FromResult(0); return Task.FromResult(0);
} }
string sessionToken = AVUser.CurrentUser.SessionToken; string sessionToken = AVUser.CurrentUser?.SessionToken;
return toAwait.OnSuccess(_ => { return toAwait.OnSuccess(_ => {
return ObjectController.DeleteAsync(State, sessionToken, cancellationToken); return ObjectController.DeleteAsync(State, sessionToken, cancellationToken);
@ -902,7 +902,7 @@ string propertyName
var states = uniqueObjects.Select(t => t.state).ToList(); var states = uniqueObjects.Select(t => t.state).ToList();
return toAwait.OnSuccess(_ => { return toAwait.OnSuccess(_ => {
var deleteTasks = ObjectController.DeleteAllAsync(states, var deleteTasks = ObjectController.DeleteAllAsync(states,
AVUser.CurrentUser.SessionToken, AVUser.CurrentUser?.SessionToken,
cancellationToken); cancellationToken);
return Task.WhenAll(deleteTasks); return Task.WhenAll(deleteTasks);