* AppRouterState.cs: chore: 使用 await/async 替换 ContinueWith/OnSuccess
* QueryTest.cs: * ObjectTest.cs: * AVObject.cs: * ObjectControllerTests.cs: * AVFileController.cs: * AVObjectController.cs: * AVCloudCodeController.cs:
parent
eda7dd43bb
commit
f3ed814d96
|
@ -40,17 +40,17 @@ namespace LeanCloud.Storage.Internal {
|
||||||
get; internal set;
|
get; internal set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DateTime FetchedAt {
|
public DateTimeOffset FetchedAt {
|
||||||
get; internal set;
|
get; internal set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AppRouterState() {
|
public AppRouterState() {
|
||||||
FetchedAt = DateTime.Now;
|
FetchedAt = DateTimeOffset.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsExpired {
|
public bool IsExpired {
|
||||||
get {
|
get {
|
||||||
return DateTime.Now > FetchedAt + TimeSpan.FromSeconds(TTL);
|
return DateTimeOffset.Now > FetchedAt.AddSeconds(TTL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,27 @@ namespace LeanCloudTests {
|
||||||
TestContext.Out.WriteLine($"balance: {account["balance"]}");
|
TestContext.Out.WriteLine($"balance: {account["balance"]}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task SaveWithPointer() {
|
||||||
|
AVObject comment = AVObject.Create("Comment");
|
||||||
|
comment["content"] = "Hello, Comment";
|
||||||
|
|
||||||
|
|
||||||
|
AVObject post = AVObject.Create("Post");
|
||||||
|
post["name"] = "New Post";
|
||||||
|
|
||||||
|
AVObject category = AVObject.Create("Category");
|
||||||
|
post["category"] = category;
|
||||||
|
|
||||||
|
comment["post"] = post;
|
||||||
|
|
||||||
|
AVObject testPost = AVObject.Create("Post");
|
||||||
|
testPost["name"] = "Test Post";
|
||||||
|
comment["test_post"] = testPost;
|
||||||
|
|
||||||
|
await comment.SaveAsync();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task SaveBatch() {
|
public async Task SaveBatch() {
|
||||||
List<AVObject> objList = new List<AVObject>();
|
List<AVObject> objList = new List<AVObject>();
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace LeanCloudTests {
|
||||||
res.Dispose();
|
res.Dispose();
|
||||||
TestContext.Out.WriteLine($"response at {Thread.CurrentThread.ManagedThreadId}");
|
TestContext.Out.WriteLine($"response at {Thread.CurrentThread.ManagedThreadId}");
|
||||||
TestContext.Out.WriteLine(data);
|
TestContext.Out.WriteLine(data);
|
||||||
Assert.Pass();
|
Assert.Pass();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
|
@ -8,12 +8,7 @@ namespace LeanCloudTests {
|
||||||
public class QueryTest {
|
public class QueryTest {
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() {
|
public void SetUp() {
|
||||||
AVClient.Initialize(new AVClient.Configuration {
|
Utils.InitNorthChina();
|
||||||
ApplicationId = "BMYV4RKSTwo8WSqt8q9ezcWF-gzGzoHsz",
|
|
||||||
ApplicationKey = "pbf6Nk5seyjilexdpyrPwjSp",
|
|
||||||
ApiServer = "https://avoscloud.com"
|
|
||||||
});
|
|
||||||
AVClient.HttpLog(TestContext.Out.WriteLine);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
|
@ -7,7 +7,7 @@ using System.Net.Http;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal {
|
namespace LeanCloud.Storage.Internal {
|
||||||
public class AVCloudCodeController {
|
public class AVCloudCodeController {
|
||||||
public Task<T> CallFunctionAsync<T>(string name,
|
public async Task<T> CallFunctionAsync<T>(string name,
|
||||||
IDictionary<string, object> parameters,
|
IDictionary<string, object> parameters,
|
||||||
CancellationToken cancellationToken) {
|
CancellationToken cancellationToken) {
|
||||||
var command = new EngineCommand {
|
var command = new EngineCommand {
|
||||||
|
@ -15,28 +15,26 @@ namespace LeanCloud.Storage.Internal {
|
||||||
Method = HttpMethod.Post,
|
Method = HttpMethod.Post,
|
||||||
Content = parameters ?? new Dictionary<string, object>()
|
Content = parameters ?? new Dictionary<string, object>()
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken).OnSuccess(t => {
|
var data = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
||||||
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
|
var decoded = AVDecoder.Instance.Decode(data.Item2) as IDictionary<string, object>;
|
||||||
if (!decoded.ContainsKey("result")) {
|
if (!decoded.ContainsKey("result")) {
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
return Conversion.To<T>(decoded["result"]);
|
return Conversion.To<T>(decoded["result"]);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<T> RPCFunction<T>(string name, IDictionary<string, object> parameters, CancellationToken cancellationToken) {
|
public async Task<T> RPCFunction<T>(string name, IDictionary<string, object> parameters, CancellationToken cancellationToken) {
|
||||||
var command = new EngineCommand {
|
var command = new EngineCommand {
|
||||||
Path = $"call/{Uri.EscapeUriString(name)}",
|
Path = $"call/{Uri.EscapeUriString(name)}",
|
||||||
Method = HttpMethod.Post,
|
Method = HttpMethod.Post,
|
||||||
Content = parameters ?? new Dictionary<string, object>()
|
Content = parameters ?? new Dictionary<string, object>()
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken).OnSuccess(t => {
|
var data = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
||||||
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
|
var decoded = AVDecoder.Instance.Decode(data.Item2) as IDictionary<string, object>;
|
||||||
if (!decoded.ContainsKey("result")) {
|
if (!decoded.ContainsKey("result")) {
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
return Conversion.To<T>(decoded["result"]);
|
return Conversion.To<T>(decoded["result"]);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,39 +17,36 @@ namespace LeanCloud.Storage.Internal {
|
||||||
const string QCloud = "qcloud";
|
const string QCloud = "qcloud";
|
||||||
const string AWS = "s3";
|
const string AWS = "s3";
|
||||||
|
|
||||||
public Task<FileState> SaveAsync(FileState state,
|
public async Task<FileState> SaveAsync(FileState state,
|
||||||
Stream dataStream,
|
Stream dataStream,
|
||||||
IProgress<AVUploadProgressEventArgs> progress,
|
IProgress<AVUploadProgressEventArgs> progress,
|
||||||
CancellationToken cancellationToken = default) {
|
CancellationToken cancellationToken = default) {
|
||||||
if (state.Url != null) {
|
if (state.Url != null) {
|
||||||
return SaveWithUrl(state);
|
return await SaveWithUrl(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetFileToken(state, cancellationToken).OnSuccess(t => {
|
var data = await GetFileToken(state, cancellationToken);
|
||||||
// 根据 provider 区分 cdn
|
var fileToken = data.Item2;
|
||||||
var ret = t.Result;
|
var provider = fileToken["provider"] as string;
|
||||||
var fileToken = ret.Item2;
|
switch (provider) {
|
||||||
var provider = fileToken["provider"] as string;
|
case QCloud:
|
||||||
switch (provider) {
|
return await new QCloudUploader().Upload(state, dataStream, fileToken, progress, cancellationToken);
|
||||||
case QCloud:
|
case AWS:
|
||||||
return new QCloudUploader().Upload(state, dataStream, fileToken, progress, cancellationToken);
|
return await new AWSUploader().Upload(state, dataStream, fileToken, progress, cancellationToken);
|
||||||
case AWS:
|
default:
|
||||||
return new AWSUploader().Upload(state, dataStream, fileToken, progress, cancellationToken);
|
return await new QiniuUploader().Upload(state, dataStream, fileToken, progress, cancellationToken);
|
||||||
default:
|
}
|
||||||
return new QiniuUploader().Upload(state, dataStream, fileToken, progress, cancellationToken);
|
|
||||||
}
|
|
||||||
}).Unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteAsync(FileState state, CancellationToken cancellationToken) {
|
public async Task DeleteAsync(FileState state, CancellationToken cancellationToken) {
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = $"files/{state.ObjectId}",
|
Path = $"files/{state.ObjectId}",
|
||||||
Method = HttpMethod.Delete
|
Method = HttpMethod.Delete
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken);
|
await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Task<FileState> SaveWithUrl(FileState state) {
|
internal async Task<FileState> SaveWithUrl(FileState state) {
|
||||||
Dictionary<string, object> strs = new Dictionary<string, object> {
|
Dictionary<string, object> strs = new Dictionary<string, object> {
|
||||||
{ "url", state.Url.ToString() },
|
{ "url", state.Url.ToString() },
|
||||||
{ "name", state.Name },
|
{ "name", state.Name },
|
||||||
|
@ -72,14 +69,13 @@ namespace LeanCloud.Storage.Internal {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(cmd).OnSuccess(t => {
|
var data = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(cmd);
|
||||||
var result = t.Result.Item2;
|
var result = data.Item2;
|
||||||
state.ObjectId = result["objectId"].ToString();
|
state.ObjectId = result["objectId"].ToString();
|
||||||
return state;
|
return state;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Task<Tuple<HttpStatusCode, IDictionary<string, object>>> GetFileToken(FileState fileState, CancellationToken cancellationToken) {
|
internal async Task<Tuple<HttpStatusCode, IDictionary<string, object>>> GetFileToken(FileState fileState, CancellationToken cancellationToken) {
|
||||||
string str = fileState.Name;
|
string str = fileState.Name;
|
||||||
IDictionary<string, object> parameters = new Dictionary<string, object> {
|
IDictionary<string, object> parameters = new Dictionary<string, object> {
|
||||||
{ "name", str },
|
{ "name", str },
|
||||||
|
@ -94,24 +90,22 @@ namespace LeanCloud.Storage.Internal {
|
||||||
Method = HttpMethod.Post,
|
Method = HttpMethod.Post,
|
||||||
Content = parameters
|
Content = parameters
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
return await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<FileState> GetAsync(string objectId, CancellationToken cancellationToken) {
|
public async Task<FileState> GetAsync(string objectId, CancellationToken cancellationToken) {
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = $"files/{objectId}",
|
Path = $"files/{objectId}",
|
||||||
Method = HttpMethod.Get
|
Method = HttpMethod.Get
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken).OnSuccess(_ => {
|
var data = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
||||||
var result = _.Result;
|
var jsonData = data.Item2;
|
||||||
var jsonData = result.Item2;
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
return new FileState {
|
||||||
return new FileState {
|
ObjectId = jsonData["objectId"] as string,
|
||||||
ObjectId = jsonData["objectId"] as string,
|
Name = jsonData["name"] as string,
|
||||||
Name = jsonData["name"] as string,
|
Url = new Uri(jsonData["url"] as string, UriKind.Absolute),
|
||||||
Url = new Uri(jsonData["url"] as string, UriKind.Absolute),
|
};
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetUniqueName(FileState state) {
|
internal static string GetUniqueName(FileState state) {
|
||||||
|
|
|
@ -8,19 +8,19 @@ using System.Net.Http;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal {
|
namespace LeanCloud.Storage.Internal {
|
||||||
public class AVObjectController {
|
public class AVObjectController {
|
||||||
public Task<IObjectState> FetchAsync(IObjectState state,
|
public async Task<IObjectState> FetchAsync(IObjectState state,
|
||||||
IDictionary<string, object> queryString,
|
IDictionary<string, object> queryString,
|
||||||
CancellationToken cancellationToken) {
|
CancellationToken cancellationToken) {
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = $"classes/{Uri.EscapeDataString(state.ClassName)}/{Uri.EscapeDataString(state.ObjectId)}?{AVClient.BuildQueryString(queryString)}",
|
Path = $"classes/{Uri.EscapeDataString(state.ClassName)}/{Uri.EscapeDataString(state.ObjectId)}?{AVClient.BuildQueryString(queryString)}",
|
||||||
Method = HttpMethod.Get
|
Method = HttpMethod.Get
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken).OnSuccess(t => {
|
var data = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
||||||
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
var objState = AVObjectCoder.Instance.Decode(data.Item2, AVDecoder.Instance);
|
||||||
});
|
return objState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IObjectState> SaveAsync(IObjectState state,
|
public async Task<IObjectState> SaveAsync(IObjectState state,
|
||||||
IDictionary<string, IAVFieldOperation> operations,
|
IDictionary<string, IAVFieldOperation> operations,
|
||||||
bool fetchWhenSave,
|
bool fetchWhenSave,
|
||||||
AVQuery<AVObject> query,
|
AVQuery<AVObject> query,
|
||||||
|
@ -44,13 +44,12 @@ namespace LeanCloud.Storage.Internal {
|
||||||
string encode = AVClient.BuildQueryString(args);
|
string encode = AVClient.BuildQueryString(args);
|
||||||
command.Path = $"{command.Path}?{encode}";
|
command.Path = $"{command.Path}?{encode}";
|
||||||
}
|
}
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken).OnSuccess(t => {
|
var data = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
||||||
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
var serverState = AVObjectCoder.Instance.Decode(data.Item2, AVDecoder.Instance);
|
||||||
serverState = serverState.MutatedClone(mutableClone => {
|
serverState = serverState.MutatedClone(mutableClone => {
|
||||||
mutableClone.IsNew = t.Result.Item1 == System.Net.HttpStatusCode.Created;
|
mutableClone.IsNew = data.Item1 == System.Net.HttpStatusCode.Created;
|
||||||
});
|
|
||||||
return serverState;
|
|
||||||
});
|
});
|
||||||
|
return serverState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IList<Task<IObjectState>> SaveAllAsync(IList<IObjectState> states,
|
public IList<Task<IObjectState>> SaveAllAsync(IList<IObjectState> states,
|
||||||
|
@ -76,13 +75,13 @@ namespace LeanCloud.Storage.Internal {
|
||||||
return stateTasks;
|
return stateTasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteAsync(IObjectState state,
|
public async Task DeleteAsync(IObjectState state,
|
||||||
CancellationToken cancellationToken) {
|
CancellationToken cancellationToken) {
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = $"classes/{state.ClassName}/{state.ObjectId}",
|
Path = $"classes/{state.ClassName}/{state.ObjectId}",
|
||||||
Method = HttpMethod.Delete
|
Method = HttpMethod.Delete
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IList<Task> DeleteAllAsync(IList<IObjectState> states,
|
public IList<Task> DeleteAllAsync(IList<IObjectState> states,
|
||||||
|
@ -99,6 +98,7 @@ namespace LeanCloud.Storage.Internal {
|
||||||
|
|
||||||
// TODO (hallucinogen): move this out to a class to be used by Analytics
|
// TODO (hallucinogen): move this out to a class to be used by Analytics
|
||||||
private const int MaximumBatchSize = 50;
|
private const int MaximumBatchSize = 50;
|
||||||
|
|
||||||
internal IList<Task<IDictionary<string, object>>> ExecuteBatchRequests(IList<AVCommand> requests,
|
internal IList<Task<IDictionary<string, object>>> ExecuteBatchRequests(IList<AVCommand> requests,
|
||||||
CancellationToken cancellationToken) {
|
CancellationToken cancellationToken) {
|
||||||
var tasks = new List<Task<IDictionary<string, object>>>();
|
var tasks = new List<Task<IDictionary<string, object>>>();
|
||||||
|
|
|
@ -814,49 +814,26 @@ string propertyName
|
||||||
|
|
||||||
#region Delete Object
|
#region Delete Object
|
||||||
|
|
||||||
internal Task DeleteAsync(Task toAwait, CancellationToken cancellationToken) {
|
/// <summary>
|
||||||
|
/// Deletes this object on the server.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
public async Task DeleteAsync(CancellationToken cancellationToken = default) {
|
||||||
if (ObjectId == null) {
|
if (ObjectId == null) {
|
||||||
return Task.FromResult(0);
|
return;
|
||||||
}
|
}
|
||||||
|
await ObjectController.DeleteAsync(State, cancellationToken);
|
||||||
return toAwait.OnSuccess(_ => {
|
IsDirty = true;
|
||||||
return ObjectController.DeleteAsync(State, cancellationToken);
|
|
||||||
}).Unwrap().OnSuccess(_ => IsDirty = true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes this object on the server.
|
|
||||||
/// </summary>
|
|
||||||
public Task DeleteAsync() {
|
|
||||||
return DeleteAsync(CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes this object on the server.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
public Task DeleteAsync(CancellationToken cancellationToken) {
|
|
||||||
return taskQueue.Enqueue(toAwait => DeleteAsync(toAwait, cancellationToken),
|
|
||||||
cancellationToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes each object in the provided list.
|
/// Deletes each object in the provided list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="objects">The objects to delete.</param>
|
/// <param name="objects">The objects to delete.</param>
|
||||||
public static Task DeleteAllAsync<T>(IEnumerable<T> objects) where T : AVObject {
|
public static Task DeleteAllAsync<T>(IEnumerable<T> objects, CancellationToken cancellationToken = default)
|
||||||
return DeleteAllAsync(objects, CancellationToken.None);
|
where T : AVObject {
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes each object in the provided list.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="objects">The objects to delete.</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
public static Task DeleteAllAsync<T>(
|
|
||||||
IEnumerable<T> objects, CancellationToken cancellationToken) where T : AVObject {
|
|
||||||
var uniqueObjects = new HashSet<AVObject>(objects.OfType<AVObject>().ToList(),
|
var uniqueObjects = new HashSet<AVObject>(objects.OfType<AVObject>().ToList(),
|
||||||
new IdentityEqualityComparer<AVObject>());
|
new IdentityEqualityComparer<AVObject>());
|
||||||
|
|
||||||
return EnqueueForAll<object>(uniqueObjects, toAwait => {
|
return EnqueueForAll<object>(uniqueObjects, toAwait => {
|
||||||
var states = uniqueObjects.Select(t => t.state).ToList();
|
var states = uniqueObjects.Select(t => t.state).ToList();
|
||||||
|
@ -1094,7 +1071,7 @@ string propertyName
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal virtual void OnSettingValue(ref string key, ref object value) {
|
internal virtual void OnSettingValue(ref string key, ref object value) {
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
throw new ArgumentNullException("key");
|
throw new ArgumentNullException(nameof(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1151,8 +1128,7 @@ string propertyName
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SetIfDifferent<T>(string key, T value) {
|
internal void SetIfDifferent<T>(string key, T value) {
|
||||||
T current;
|
bool hasCurrent = TryGetValue<T>(key, out T current);
|
||||||
bool hasCurrent = TryGetValue<T>(key, out current);
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
if (hasCurrent) {
|
if (hasCurrent) {
|
||||||
PerformOperation(key, AVDeleteOperation.Instance);
|
PerformOperation(key, AVDeleteOperation.Instance);
|
||||||
|
@ -1313,10 +1289,10 @@ string propertyName
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public AVQuery<T> GetRelationRevserseQuery<T>(string parentClassName, string key) where T : AVObject {
|
public AVQuery<T> GetRelationRevserseQuery<T>(string parentClassName, string key) where T : AVObject {
|
||||||
if (string.IsNullOrEmpty(parentClassName)) {
|
if (string.IsNullOrEmpty(parentClassName)) {
|
||||||
throw new ArgumentNullException("parentClassName", "can not query a relation without parentClassName.");
|
throw new ArgumentNullException(nameof(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.");
|
throw new ArgumentNullException(nameof(key), "can not query a relation without key.");
|
||||||
}
|
}
|
||||||
return new AVQuery<T>(parentClassName).WhereEqualTo(key, this);
|
return new AVQuery<T>(parentClassName).WhereEqualTo(key, this);
|
||||||
}
|
}
|
||||||
|
@ -1604,7 +1580,7 @@ string propertyName
|
||||||
// types.
|
// types.
|
||||||
if (SubclassingController.GetType(className) != null) {
|
if (SubclassingController.GetType(className) != null) {
|
||||||
throw new ArgumentException(
|
throw new ArgumentException(
|
||||||
"Use the class-specific query properties for class " + className, "className");
|
"Use the class-specific query properties for class " + className, nameof(className));
|
||||||
}
|
}
|
||||||
return new AVQuery<AVObject>(className);
|
return new AVQuery<AVObject>(className);
|
||||||
}
|
}
|
||||||
|
@ -1665,7 +1641,7 @@ string propertyName
|
||||||
}
|
}
|
||||||
|
|
||||||
private SynchronizedEventHandler<PropertyUpdatedEventArgs> propertyUpdated =
|
private SynchronizedEventHandler<PropertyUpdatedEventArgs> propertyUpdated =
|
||||||
new SynchronizedEventHandler<PropertyUpdatedEventArgs>();
|
new SynchronizedEventHandler<PropertyUpdatedEventArgs>();
|
||||||
|
|
||||||
public event PropertyUpdatedEventHandler PropertyUpdated {
|
public event PropertyUpdatedEventHandler PropertyUpdated {
|
||||||
add {
|
add {
|
||||||
|
@ -1681,7 +1657,7 @@ string propertyName
|
||||||
}
|
}
|
||||||
|
|
||||||
private SynchronizedEventHandler<CollectionPropertyUpdatedEventArgs> collectionUpdated =
|
private SynchronizedEventHandler<CollectionPropertyUpdatedEventArgs> collectionUpdated =
|
||||||
new SynchronizedEventHandler<CollectionPropertyUpdatedEventArgs>();
|
new SynchronizedEventHandler<CollectionPropertyUpdatedEventArgs>();
|
||||||
|
|
||||||
public event CollectionPropertyUpdatedEventHandler CollectionPropertyUpdated {
|
public event CollectionPropertyUpdatedEventHandler CollectionPropertyUpdated {
|
||||||
add {
|
add {
|
||||||
|
|
Loading…
Reference in New Issue