* AVCorePlugins.cs: chore: 将 AVObject 中的属性 ACL 单独处理
* AVObject.cs: * IObjectState.cs: * MutableObjectState.cs: * PointerOrLocalIdEncoder.cs: * AVUserController.cs: * AVObjectController.cs:
parent
fcb513aee3
commit
148c4d6ae2
|
@ -22,7 +22,6 @@ namespace LeanCloud.Storage.Internal {
|
||||||
|
|
||||||
private AVCloudCodeController cloudCodeController;
|
private AVCloudCodeController cloudCodeController;
|
||||||
private AVFileController fileController;
|
private AVFileController fileController;
|
||||||
private AVObjectController objectController;
|
|
||||||
private AVQueryController queryController;
|
private AVQueryController queryController;
|
||||||
private AVUserController userController;
|
private AVUserController userController;
|
||||||
private ObjectSubclassingController subclassingController;
|
private ObjectSubclassingController subclassingController;
|
||||||
|
@ -42,7 +41,6 @@ namespace LeanCloud.Storage.Internal {
|
||||||
|
|
||||||
CloudCodeController = null;
|
CloudCodeController = null;
|
||||||
FileController = null;
|
FileController = null;
|
||||||
ObjectController = null;
|
|
||||||
UserController = null;
|
UserController = null;
|
||||||
SubclassingController = null;
|
SubclassingController = null;
|
||||||
|
|
||||||
|
@ -108,20 +106,6 @@ namespace LeanCloud.Storage.Internal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AVObjectController ObjectController {
|
|
||||||
get {
|
|
||||||
lock (mutex) {
|
|
||||||
objectController = objectController ?? new AVObjectController();
|
|
||||||
return objectController;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
lock (mutex) {
|
|
||||||
objectController = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public AVQueryController QueryController {
|
public AVQueryController QueryController {
|
||||||
get {
|
get {
|
||||||
lock (mutex) {
|
lock (mutex) {
|
||||||
|
|
|
@ -46,24 +46,21 @@ namespace LeanCloud.Storage.Internal
|
||||||
var operations = value.GetCurrentOperations();
|
var operations = value.GetCurrentOperations();
|
||||||
var operationJSON = AVObject.ToJSONObjectForSaving(operations);
|
var operationJSON = AVObject.ToJSONObjectForSaving(operations);
|
||||||
var objectJSON = value.ToDictionary(kvp => kvp.Key, kvp => PointerOrLocalIdEncoder.Instance.Encode(kvp.Value));
|
var objectJSON = value.ToDictionary(kvp => kvp.Key, kvp => PointerOrLocalIdEncoder.Instance.Encode(kvp.Value));
|
||||||
foreach (var kvp in operationJSON)
|
foreach (var kvp in operationJSON) {
|
||||||
{
|
|
||||||
objectJSON[kvp.Key] = kvp.Value;
|
objectJSON[kvp.Key] = kvp.Value;
|
||||||
}
|
}
|
||||||
if (value.CreatedAt.HasValue)
|
if (value.CreatedAt.HasValue) {
|
||||||
{
|
objectJSON["createdAt"] = value.CreatedAt.Value.ToString(AVClient.DateFormatStrings.First(), CultureInfo.InvariantCulture);
|
||||||
objectJSON["createdAt"] = value.CreatedAt.Value.ToString(AVClient.DateFormatStrings.First(),
|
|
||||||
CultureInfo.InvariantCulture);
|
|
||||||
}
|
}
|
||||||
if (value.UpdatedAt.HasValue)
|
if (value.UpdatedAt.HasValue) {
|
||||||
{
|
objectJSON["updatedAt"] = value.UpdatedAt.Value.ToString(AVClient.DateFormatStrings.First(), CultureInfo.InvariantCulture);
|
||||||
objectJSON["updatedAt"] = value.UpdatedAt.Value.ToString(AVClient.DateFormatStrings.First(),
|
|
||||||
CultureInfo.InvariantCulture);
|
|
||||||
}
|
}
|
||||||
if(!string.IsNullOrEmpty(value.ObjectId))
|
if(!string.IsNullOrEmpty(value.ObjectId)) {
|
||||||
{
|
|
||||||
objectJSON["objectId"] = value.ObjectId;
|
objectJSON["objectId"] = value.ObjectId;
|
||||||
}
|
}
|
||||||
|
if (value.ACL != null) {
|
||||||
|
objectJSON["acl"] = Encode(value.ACL);
|
||||||
|
}
|
||||||
objectJSON["className"] = value.ClassName;
|
objectJSON["className"] = value.ClassName;
|
||||||
objectJSON["__type"] = "Object";
|
objectJSON["__type"] = "Object";
|
||||||
return objectJSON;
|
return objectJSON;
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal {
|
|
||||||
public class AVObjectController {
|
|
||||||
public async Task<IObjectState> FetchAsync(IObjectState state,
|
|
||||||
IDictionary<string, object> queryString,
|
|
||||||
CancellationToken cancellationToken) {
|
|
||||||
var command = new AVCommand {
|
|
||||||
Path = $"classes/{Uri.EscapeDataString(state.ClassName)}/{Uri.EscapeDataString(state.ObjectId)}?{AVClient.BuildQueryString(queryString)}",
|
|
||||||
Method = HttpMethod.Get
|
|
||||||
};
|
|
||||||
var data = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
|
||||||
var objState = AVObjectCoder.Instance.Decode(data.Item2, AVDecoder.Instance);
|
|
||||||
return objState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IObjectState> SaveAsync(IObjectState state,
|
|
||||||
IDictionary<string, IAVFieldOperation> operations,
|
|
||||||
bool fetchWhenSave,
|
|
||||||
AVQuery<AVObject> query,
|
|
||||||
CancellationToken cancellationToken) {
|
|
||||||
var objectJSON = AVObject.ToJSONObjectForSaving(operations);
|
|
||||||
|
|
||||||
var command = new AVCommand {
|
|
||||||
Path = state.ObjectId == null ? $"classes/{Uri.EscapeDataString(state.ClassName)}" : $"classes/{Uri.EscapeDataString(state.ClassName)}/{state.ObjectId}",
|
|
||||||
Method = state.ObjectId == null ? HttpMethod.Post : HttpMethod.Put,
|
|
||||||
Content = objectJSON
|
|
||||||
};
|
|
||||||
Dictionary<string, object> args = new Dictionary<string, object>();
|
|
||||||
if (fetchWhenSave) {
|
|
||||||
args.Add("fetchWhenSave", fetchWhenSave);
|
|
||||||
}
|
|
||||||
// 查询条件
|
|
||||||
if (query != null) {
|
|
||||||
args.Add("where", query.BuildWhere());
|
|
||||||
}
|
|
||||||
if (args.Count > 0) {
|
|
||||||
string encode = AVClient.BuildQueryString(args);
|
|
||||||
command.Path = $"{command.Path}?{encode}";
|
|
||||||
}
|
|
||||||
var data = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
|
||||||
var serverState = AVObjectCoder.Instance.Decode(data.Item2, AVDecoder.Instance);
|
|
||||||
serverState = serverState.MutatedClone(mutableClone => {
|
|
||||||
mutableClone.IsNew = data.Item1 == System.Net.HttpStatusCode.Created;
|
|
||||||
});
|
|
||||||
return serverState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IList<IObjectState>> SaveAllAsync(IList<IObjectState> states,
|
|
||||||
IList<IDictionary<string, IAVFieldOperation>> operationsList,
|
|
||||||
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)}",
|
|
||||||
Method = item.ObjectId == null ? HttpMethod.Post : HttpMethod.Put,
|
|
||||||
Content = AVObject.ToJSONObjectForSaving(ops)
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
IList<IObjectState> list = new List<IObjectState>();
|
|
||||||
var result = await AVPlugins.Instance.CommandRunner.ExecuteBatchRequests(requests, cancellationToken);
|
|
||||||
foreach (var data in result) {
|
|
||||||
if (data.TryGetValue("success", out object val)) {
|
|
||||||
IObjectState obj = AVObjectCoder.Instance.Decode(val as IDictionary<string, object>, AVDecoder.Instance);
|
|
||||||
list.Add(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IList<IObjectState>> SaveAllAsync(IList<AVObject> avObjects, CancellationToken cancellationToken) {
|
|
||||||
List<AVCommand> commandList = new List<AVCommand>();
|
|
||||||
foreach (AVObject avObj in avObjects) {
|
|
||||||
AVCommand command = new AVCommand {
|
|
||||||
Path = avObj.ObjectId == null ? $"classes/{Uri.EscapeDataString(avObj.ClassName)}" : $"classes/{Uri.EscapeDataString(avObj.ClassName)}/{Uri.EscapeDataString(avObj.ObjectId)}",
|
|
||||||
Method = avObj.ObjectId == null ? HttpMethod.Post : HttpMethod.Put,
|
|
||||||
Content = AVObject.ToJSONObjectForSaving(avObj.operationDict)
|
|
||||||
};
|
|
||||||
commandList.Add(command);
|
|
||||||
}
|
|
||||||
IList<IObjectState> list = new List<IObjectState>();
|
|
||||||
var result = await AVPlugins.Instance.CommandRunner.ExecuteBatchRequests(commandList, cancellationToken);
|
|
||||||
foreach (var data in result) {
|
|
||||||
if (data.TryGetValue("success", out object val)) {
|
|
||||||
IObjectState obj = AVObjectCoder.Instance.Decode(val as IDictionary<string, object>, AVDecoder.Instance);
|
|
||||||
list.Add(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal
|
namespace LeanCloud.Storage.Internal {
|
||||||
{
|
public interface IObjectState : IEnumerable<KeyValuePair<string, object>> {
|
||||||
public interface IObjectState : IEnumerable<KeyValuePair<string, object>>
|
|
||||||
{
|
|
||||||
bool IsNew { get; }
|
|
||||||
string ClassName { get; }
|
string ClassName { get; }
|
||||||
string ObjectId { get; }
|
string ObjectId { get; }
|
||||||
|
AVACL ACL { get; set; }
|
||||||
DateTime? UpdatedAt { get; }
|
DateTime? UpdatedAt { get; }
|
||||||
DateTime? CreatedAt { get; }
|
DateTime? CreatedAt { get; }
|
||||||
object this[string key] { get; }
|
object this[string key] { get; }
|
||||||
|
|
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal {
|
namespace LeanCloud.Storage.Internal {
|
||||||
public class MutableObjectState : IObjectState {
|
public class MutableObjectState : IObjectState {
|
||||||
public bool IsNew { get; set; }
|
|
||||||
public string ClassName { get; set; }
|
public string ClassName { get; set; }
|
||||||
public string ObjectId { get; set; }
|
public string ObjectId { get; set; }
|
||||||
public AVACL ACL { get; set; }
|
public AVACL ACL { get; set; }
|
||||||
|
@ -38,13 +37,12 @@ namespace LeanCloud.Storage.Internal {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Apply(IObjectState other) {
|
public void Apply(IObjectState other) {
|
||||||
IsNew = other.IsNew;
|
|
||||||
if (other.ObjectId != null) {
|
if (other.ObjectId != null) {
|
||||||
ObjectId = other.ObjectId;
|
ObjectId = other.ObjectId;
|
||||||
}
|
}
|
||||||
//if (other.ACL != null) {
|
if (other.ACL != null) {
|
||||||
|
ACL = other.ACL;
|
||||||
//}
|
}
|
||||||
if (other.UpdatedAt != null) {
|
if (other.UpdatedAt != null) {
|
||||||
UpdatedAt = other.UpdatedAt;
|
UpdatedAt = other.UpdatedAt;
|
||||||
}
|
}
|
||||||
|
@ -65,7 +63,6 @@ namespace LeanCloud.Storage.Internal {
|
||||||
|
|
||||||
protected virtual MutableObjectState MutableClone() {
|
protected virtual MutableObjectState MutableClone() {
|
||||||
return new MutableObjectState {
|
return new MutableObjectState {
|
||||||
IsNew = IsNew,
|
|
||||||
ClassName = ClassName,
|
ClassName = ClassName,
|
||||||
ObjectId = ObjectId,
|
ObjectId = ObjectId,
|
||||||
CreatedAt = CreatedAt,
|
CreatedAt = CreatedAt,
|
||||||
|
|
|
@ -14,9 +14,6 @@ namespace LeanCloud.Storage.Internal {
|
||||||
};
|
};
|
||||||
var ret = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
var ret = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
var serverState = AVObjectCoder.Instance.Decode(ret.Item2, AVDecoder.Instance);
|
var serverState = AVObjectCoder.Instance.Decode(ret.Item2, AVDecoder.Instance);
|
||||||
serverState = serverState.MutatedClone(mutableClone => {
|
|
||||||
mutableClone.IsNew = true;
|
|
||||||
});
|
|
||||||
return serverState;
|
return serverState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,9 +34,6 @@ namespace LeanCloud.Storage.Internal {
|
||||||
};
|
};
|
||||||
var ret = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
var ret = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
var serverState = AVObjectCoder.Instance.Decode(ret.Item2, AVDecoder.Instance);
|
var serverState = AVObjectCoder.Instance.Decode(ret.Item2, AVDecoder.Instance);
|
||||||
serverState = serverState.MutatedClone(mutableClone => {
|
|
||||||
mutableClone.IsNew = ret.Item1 == System.Net.HttpStatusCode.Created;
|
|
||||||
});
|
|
||||||
return serverState;
|
return serverState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +51,6 @@ namespace LeanCloud.Storage.Internal {
|
||||||
};
|
};
|
||||||
var ret = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
var ret = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
var serverState = AVObjectCoder.Instance.Decode(ret.Item2, AVDecoder.Instance);
|
var serverState = AVObjectCoder.Instance.Decode(ret.Item2, AVDecoder.Instance);
|
||||||
serverState = serverState.MutatedClone(mutableClone => {
|
|
||||||
mutableClone.IsNew = ret.Item1 == System.Net.HttpStatusCode.Created;
|
|
||||||
});
|
|
||||||
return serverState;
|
return serverState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,9 +85,6 @@ namespace LeanCloud.Storage.Internal {
|
||||||
};
|
};
|
||||||
var ret = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
var ret = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
var serverState = AVObjectCoder.Instance.Decode(ret.Item2, AVDecoder.Instance);
|
var serverState = AVObjectCoder.Instance.Decode(ret.Item2, AVDecoder.Instance);
|
||||||
serverState = serverState.MutatedClone(mutableClone => {
|
|
||||||
mutableClone.IsNew = ret.Item1 == System.Net.HttpStatusCode.Created;
|
|
||||||
});
|
|
||||||
return serverState;
|
return serverState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,16 +35,16 @@ namespace LeanCloud {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal AVACL acl;
|
||||||
|
|
||||||
[AVFieldName("ACL")]
|
[AVFieldName("ACL")]
|
||||||
public AVACL ACL {
|
public AVACL ACL {
|
||||||
|
// 设置 IsDirty
|
||||||
get {
|
get {
|
||||||
return GetProperty<AVACL>(null, "ACL");
|
return acl;
|
||||||
}
|
} set {
|
||||||
set {
|
acl = value;
|
||||||
IsDirty = true;
|
IsDirty = true;
|
||||||
MutateState(mutableClone => {
|
|
||||||
mutableClone.ACL = value;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,12 +89,6 @@ namespace LeanCloud {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static AVObjectController ObjectController {
|
|
||||||
get {
|
|
||||||
return AVPlugins.Instance.ObjectController;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static ObjectSubclassingController SubclassingController {
|
internal static ObjectSubclassingController SubclassingController {
|
||||||
get {
|
get {
|
||||||
return AVPlugins.Instance.SubclassingController;
|
return AVPlugins.Instance.SubclassingController;
|
||||||
|
@ -261,6 +255,17 @@ namespace LeanCloud {
|
||||||
RebuildEstimatedData();
|
RebuildEstimatedData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal IDictionary<string, object> ToJSONObject() {
|
||||||
|
IDictionary<string, object> result = new Dictionary<string, object>();
|
||||||
|
if (ACL != null) {
|
||||||
|
result["ACL"] = PointerOrLocalIdEncoder.Instance.Encode(ACL);
|
||||||
|
}
|
||||||
|
foreach (KeyValuePair<string, IAVFieldOperation> kv in operationDict) {
|
||||||
|
result[kv.Key] = PointerOrLocalIdEncoder.Instance.Encode(kv.Value);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static IDictionary<string, object> ToJSONObjectForSaving(IDictionary<string, IAVFieldOperation> operations) {
|
public static IDictionary<string, object> ToJSONObjectForSaving(IDictionary<string, IAVFieldOperation> operations) {
|
||||||
var result = new Dictionary<string, object>();
|
var result = new Dictionary<string, object>();
|
||||||
foreach (var pair in operations) {
|
foreach (var pair in operations) {
|
||||||
|
@ -296,8 +301,29 @@ namespace LeanCloud {
|
||||||
}
|
}
|
||||||
Stack<Batch> batches = BatchObjects(new List<AVObject> { this }, false);
|
Stack<Batch> batches = BatchObjects(new List<AVObject> { this }, false);
|
||||||
await SaveBatches(batches, cancellationToken);
|
await SaveBatches(batches, cancellationToken);
|
||||||
IObjectState result = await ObjectController.SaveAsync(state, operationDict, fetchWhenSave, query, cancellationToken);
|
|
||||||
HandleSave(result);
|
IDictionary<string, object> objectJSON = ToJSONObject();
|
||||||
|
var command = new AVCommand {
|
||||||
|
Path = ObjectId == null ? $"classes/{Uri.EscapeDataString(ClassName)}" :
|
||||||
|
$"classes/{Uri.EscapeDataString(ClassName)}/{ObjectId}",
|
||||||
|
Method = ObjectId == null ? HttpMethod.Post : HttpMethod.Put,
|
||||||
|
Content = objectJSON
|
||||||
|
};
|
||||||
|
Dictionary<string, object> args = new Dictionary<string, object>();
|
||||||
|
if (fetchWhenSave) {
|
||||||
|
args.Add("fetchWhenSave", fetchWhenSave);
|
||||||
|
}
|
||||||
|
// 查询条件
|
||||||
|
if (query != null) {
|
||||||
|
args.Add("where", query.BuildWhere());
|
||||||
|
}
|
||||||
|
if (args.Count > 0) {
|
||||||
|
string encode = AVClient.BuildQueryString(args);
|
||||||
|
command.Path = $"{command.Path}?{encode}";
|
||||||
|
}
|
||||||
|
var data = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
||||||
|
IObjectState serverState = AVObjectCoder.Instance.Decode(data.Item2, AVDecoder.Instance);
|
||||||
|
HandleSave(serverState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task SaveAllAsync<T>(IEnumerable<T> objects, CancellationToken cancellationToken = default)
|
public static async Task SaveAllAsync<T>(IEnumerable<T> objects, CancellationToken cancellationToken = default)
|
||||||
|
@ -315,10 +341,28 @@ namespace LeanCloud {
|
||||||
while (batches.Any()) {
|
while (batches.Any()) {
|
||||||
Batch batch = batches.Pop();
|
Batch batch = batches.Pop();
|
||||||
IList<AVObject> dirtyObjects = batch.Objects.Where(o => o.IsDirty).ToList();
|
IList<AVObject> dirtyObjects = batch.Objects.Where(o => o.IsDirty).ToList();
|
||||||
var serverStates = await ObjectController.SaveAllAsync(dirtyObjects, cancellationToken);
|
|
||||||
|
List<AVCommand> commandList = new List<AVCommand>();
|
||||||
|
foreach (AVObject avObj in dirtyObjects) {
|
||||||
|
AVCommand command = new AVCommand {
|
||||||
|
Path = avObj.ObjectId == null ? $"classes/{Uri.EscapeDataString(avObj.ClassName)}" :
|
||||||
|
$"classes/{Uri.EscapeDataString(avObj.ClassName)}/{Uri.EscapeDataString(avObj.ObjectId)}",
|
||||||
|
Method = avObj.ObjectId == null ? HttpMethod.Post : HttpMethod.Put,
|
||||||
|
Content = avObj.ToJSONObject()
|
||||||
|
};
|
||||||
|
commandList.Add(command);
|
||||||
|
}
|
||||||
|
IList<IObjectState> list = new List<IObjectState>();
|
||||||
|
var result = await AVPlugins.Instance.CommandRunner.ExecuteBatchRequests(commandList, cancellationToken);
|
||||||
|
foreach (var data in result) {
|
||||||
|
if (data.TryGetValue("success", out object val)) {
|
||||||
|
IObjectState obj = AVObjectCoder.Instance.Decode(val as IDictionary<string, object>, AVDecoder.Instance);
|
||||||
|
list.Add(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
foreach (var pair in dirtyObjects.Zip(serverStates, (item, state) => new { item, state })) {
|
foreach (var pair in dirtyObjects.Zip(list, (item, state) => new { item, state })) {
|
||||||
pair.item.HandleSave(pair.state);
|
pair.item.HandleSave(pair.state);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -334,7 +378,14 @@ namespace LeanCloud {
|
||||||
if (queryString == null) {
|
if (queryString == null) {
|
||||||
queryString = new Dictionary<string, object>();
|
queryString = new Dictionary<string, object>();
|
||||||
}
|
}
|
||||||
IObjectState objectState = await ObjectController.FetchAsync(state, queryString, cancellationToken);
|
|
||||||
|
var command = new AVCommand {
|
||||||
|
Path = $"classes/{Uri.EscapeDataString(state.ClassName)}/{Uri.EscapeDataString(state.ObjectId)}?{AVClient.BuildQueryString(queryString)}",
|
||||||
|
Method = HttpMethod.Get
|
||||||
|
};
|
||||||
|
var data = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
||||||
|
IObjectState objectState = AVObjectCoder.Instance.Decode(data.Item2, AVDecoder.Instance);
|
||||||
|
|
||||||
HandleFetchResult(objectState);
|
HandleFetchResult(objectState);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue