* AVUserExtensions.cs: chore
* AVFile.cs: * AVObject.cs:
parent
8f7dcc080d
commit
e6280b828d
|
@ -1,22 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 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.
|
|
||||||
/// </summary>
|
|
||||||
public static class AVUserExtensions
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,7 +23,7 @@ namespace LeanCloud {
|
||||||
/// await obj.SaveAsync();
|
/// await obj.SaveAsync();
|
||||||
/// </code>
|
/// </code>
|
||||||
/// </example>
|
/// </example>
|
||||||
public partial class AVFile : IJsonConvertible {
|
public class AVFile : IJsonConvertible {
|
||||||
internal static int objectCounter = 0;
|
internal static int objectCounter = 0;
|
||||||
internal static readonly object Mutex = new object();
|
internal static readonly object Mutex = new object();
|
||||||
private FileState state;
|
private FileState state;
|
||||||
|
@ -45,7 +45,7 @@ namespace LeanCloud {
|
||||||
MimeType = mimeType,
|
MimeType = mimeType,
|
||||||
MetaData = metaData
|
MetaData = metaData
|
||||||
};
|
};
|
||||||
this.dataStream = data;
|
dataStream = data;
|
||||||
lock (Mutex) {
|
lock (Mutex) {
|
||||||
objectCounter++;
|
objectCounter++;
|
||||||
state.counter = objectCounter;
|
state.counter = objectCounter;
|
||||||
|
@ -132,7 +132,7 @@ namespace LeanCloud {
|
||||||
objectCounter++;
|
objectCounter++;
|
||||||
state.counter = objectCounter;
|
state.counter = objectCounter;
|
||||||
}
|
}
|
||||||
this.isExternal = true;
|
isExternal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -187,7 +187,7 @@ namespace LeanCloud {
|
||||||
}
|
}
|
||||||
|
|
||||||
internal AVFile(FileState filestate) {
|
internal AVFile(FileState filestate) {
|
||||||
this.state = filestate;
|
state = filestate;
|
||||||
}
|
}
|
||||||
internal AVFile(string objectId)
|
internal AVFile(string objectId)
|
||||||
: this(new FileState() {
|
: this(new FileState() {
|
||||||
|
@ -258,7 +258,7 @@ namespace LeanCloud {
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
IDictionary<string, object> IJsonConvertible.ToJSON() {
|
IDictionary<string, object> IJsonConvertible.ToJSON() {
|
||||||
if (this.IsDirty) {
|
if (IsDirty) {
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
"AVFile must be saved before it can be serialized.");
|
"AVFile must be saved before it can be serialized.");
|
||||||
}
|
}
|
||||||
|
@ -292,14 +292,14 @@ namespace LeanCloud {
|
||||||
internal Task SaveExternal() {
|
internal Task SaveExternal() {
|
||||||
Dictionary<string, object> strs = new Dictionary<string, object>()
|
Dictionary<string, object> strs = new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
{ "url", this.Url.ToString() },
|
{ "url", Url.ToString() },
|
||||||
{ "name",this.Name },
|
{ "name", Name },
|
||||||
{ "mime_type",this.MimeType},
|
{ "mime_type", MimeType},
|
||||||
{ "metaData",this.MetaData}
|
{ "metaData", MetaData}
|
||||||
};
|
};
|
||||||
AVCommand cmd = null;
|
AVCommand cmd = null;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(this.ObjectId)) {
|
if (!string.IsNullOrEmpty(ObjectId)) {
|
||||||
cmd = new AVCommand {
|
cmd = new AVCommand {
|
||||||
Path = $"files/{ObjectId}",
|
Path = $"files/{ObjectId}",
|
||||||
Method = HttpMethod.Put,
|
Method = HttpMethod.Put,
|
||||||
|
@ -331,7 +331,7 @@ namespace LeanCloud {
|
||||||
public string ObjectId {
|
public string ObjectId {
|
||||||
get {
|
get {
|
||||||
string str;
|
string str;
|
||||||
lock (this.mutex) {
|
lock (mutex) {
|
||||||
str = state.ObjectId;
|
str = state.ObjectId;
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
|
@ -359,8 +359,7 @@ namespace LeanCloud {
|
||||||
}
|
}
|
||||||
|
|
||||||
static AVFile() {
|
static AVFile() {
|
||||||
Dictionary<string, string> strs = new Dictionary<string, string>()
|
Dictionary<string, string> strs = new Dictionary<string, string> {
|
||||||
{
|
|
||||||
{ "ai", "application/postscript" },
|
{ "ai", "application/postscript" },
|
||||||
{ "aif", "audio/x-aiff" },
|
{ "aif", "audio/x-aiff" },
|
||||||
{ "aifc", "audio/x-aiff" },
|
{ "aifc", "audio/x-aiff" },
|
||||||
|
@ -550,15 +549,15 @@ namespace LeanCloud {
|
||||||
{ "xyz", "chemical/x-xyz" },
|
{ "xyz", "chemical/x-xyz" },
|
||||||
{ "zip", "application/zip" },
|
{ "zip", "application/zip" },
|
||||||
};
|
};
|
||||||
AVFile.MIMETypesDictionary = strs;
|
MIMETypesDictionary = strs;
|
||||||
}
|
}
|
||||||
internal static string GetMIMEType(string fileName) {
|
internal static string GetMIMEType(string fileName) {
|
||||||
try {
|
try {
|
||||||
string str = Path.GetExtension(fileName).Remove(0, 1);
|
string str = Path.GetExtension(fileName).Remove(0, 1);
|
||||||
if (!AVFile.MIMETypesDictionary.ContainsKey(str)) {
|
if (!MIMETypesDictionary.ContainsKey(str)) {
|
||||||
return "unknown/unknown";
|
return "unknown/unknown";
|
||||||
}
|
}
|
||||||
return AVFile.MIMETypesDictionary[str];
|
return MIMETypesDictionary[str];
|
||||||
} catch {
|
} catch {
|
||||||
return "unknown/unknown";
|
return "unknown/unknown";
|
||||||
}
|
}
|
||||||
|
@ -585,11 +584,12 @@ namespace LeanCloud {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AVFile CreateWithData(string objectId, string name, string url, IDictionary<string, object> metaData) {
|
public static AVFile CreateWithData(string objectId, string name, string url, IDictionary<string, object> metaData) {
|
||||||
var fileState = new FileState();
|
var fileState = new FileState {
|
||||||
fileState.Name = name;
|
Name = name,
|
||||||
fileState.ObjectId = objectId;
|
ObjectId = objectId,
|
||||||
fileState.Url = new Uri(url);
|
Url = new Uri(url),
|
||||||
fileState.MetaData = metaData;
|
MetaData = metaData
|
||||||
|
};
|
||||||
return CreateWithState(fileState);
|
return CreateWithState(fileState);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -602,7 +602,7 @@ namespace LeanCloud {
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void MergeFromJSON(IDictionary<string, object> jsonData) {
|
internal void MergeFromJSON(IDictionary<string, object> jsonData) {
|
||||||
lock (this.mutex) {
|
lock (mutex) {
|
||||||
state.ObjectId = jsonData["objectId"] as string;
|
state.ObjectId = jsonData["objectId"] as string;
|
||||||
state.Url = new Uri(jsonData["url"] as string, UriKind.Absolute);
|
state.Url = new Uri(jsonData["url"] as string, UriKind.Absolute);
|
||||||
if (jsonData.ContainsKey("name")) {
|
if (jsonData.ContainsKey("name")) {
|
||||||
|
|
|
@ -4,8 +4,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -13,19 +11,8 @@ using System.Collections;
|
||||||
|
|
||||||
namespace LeanCloud {
|
namespace LeanCloud {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The AVObject is a local representation of data that can be saved and
|
/// AVObject
|
||||||
/// retrieved from the LeanCloud cloud.</summary>
|
/// </summary>
|
||||||
/// <remarks>
|
|
||||||
/// <para>
|
|
||||||
/// The basic workflow for creating new data is to construct a new AVObject,
|
|
||||||
/// use the indexer to fill it with data, and then use SaveAsync() to persist to the
|
|
||||||
/// database.
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// The basic workflow for accessing existing data is to use a AVQuery
|
|
||||||
/// to specify which existing data to retrieve.
|
|
||||||
/// </para>
|
|
||||||
/// </remarks>
|
|
||||||
public class AVObject : IEnumerable<KeyValuePair<string, object>>, INotifyPropertyChanged, INotifyPropertyUpdated, INotifyCollectionPropertyUpdated {
|
public class AVObject : IEnumerable<KeyValuePair<string, object>>, INotifyPropertyChanged, INotifyPropertyUpdated, INotifyCollectionPropertyUpdated {
|
||||||
private static readonly string AutoClassName = "_Automatic";
|
private static readonly string AutoClassName = "_Automatic";
|
||||||
|
|
||||||
|
@ -615,7 +602,7 @@ string propertyName
|
||||||
var saveDirtyFileTasks = DeepTraversal(obj, true)
|
var saveDirtyFileTasks = DeepTraversal(obj, true)
|
||||||
.OfType<AVFile>()
|
.OfType<AVFile>()
|
||||||
.Where(f => f.IsDirty)
|
.Where(f => f.IsDirty)
|
||||||
.Select(f => f.SaveAsync(cancellationToken)).ToList();
|
.Select(f => f.SaveAsync(cancellationToken: cancellationToken)).ToList();
|
||||||
|
|
||||||
return Task.WhenAll(saveDirtyFileTasks).OnSuccess(_ => {
|
return Task.WhenAll(saveDirtyFileTasks).OnSuccess(_ => {
|
||||||
IEnumerable<AVObject> remaining = new List<AVObject>(uniqueObjects);
|
IEnumerable<AVObject> remaining = new List<AVObject>(uniqueObjects);
|
||||||
|
@ -740,7 +727,7 @@ string propertyName
|
||||||
/// <returns>The list passed in for convenience.</returns>
|
/// <returns>The list passed in for convenience.</returns>
|
||||||
public static Task<IEnumerable<T>> FetchAllIfNeededAsync<T>(
|
public static Task<IEnumerable<T>> FetchAllIfNeededAsync<T>(
|
||||||
IEnumerable<T> objects, CancellationToken cancellationToken) where T : AVObject {
|
IEnumerable<T> objects, CancellationToken cancellationToken) where T : AVObject {
|
||||||
return AVObject.EnqueueForAll(objects.Cast<AVObject>(), (Task toAwait) => {
|
return EnqueueForAll(objects.Cast<AVObject>(), (Task toAwait) => {
|
||||||
return FetchAllInternalAsync(objects, false, toAwait, cancellationToken);
|
return FetchAllInternalAsync(objects, false, toAwait, cancellationToken);
|
||||||
}, cancellationToken);
|
}, cancellationToken);
|
||||||
}
|
}
|
||||||
|
@ -763,7 +750,7 @@ string propertyName
|
||||||
/// <returns>The list passed in for convenience.</returns>
|
/// <returns>The list passed in for convenience.</returns>
|
||||||
public static Task<IEnumerable<T>> FetchAllAsync<T>(
|
public static Task<IEnumerable<T>> FetchAllAsync<T>(
|
||||||
IEnumerable<T> objects, CancellationToken cancellationToken) where T : AVObject {
|
IEnumerable<T> objects, CancellationToken cancellationToken) where T : AVObject {
|
||||||
return AVObject.EnqueueForAll(objects.Cast<AVObject>(), (Task toAwait) => {
|
return EnqueueForAll(objects.Cast<AVObject>(), (Task toAwait) => {
|
||||||
return FetchAllInternalAsync(objects, true, toAwait, cancellationToken);
|
return FetchAllInternalAsync(objects, true, toAwait, cancellationToken);
|
||||||
}, cancellationToken);
|
}, cancellationToken);
|
||||||
}
|
}
|
||||||
|
@ -872,7 +859,7 @@ string propertyName
|
||||||
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 AVObject.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();
|
||||||
return toAwait.OnSuccess(_ => {
|
return toAwait.OnSuccess(_ => {
|
||||||
var deleteTasks = ObjectController.DeleteAllAsync(states, cancellationToken);
|
var deleteTasks = ObjectController.DeleteAllAsync(states, cancellationToken);
|
||||||
|
|
Loading…
Reference in New Issue