diff --git a/Storage/Storage.Test/BaseTest.cs b/Storage/Storage.Test/BaseTest.cs index cd2a0e6..310e71d 100644 --- a/Storage/Storage.Test/BaseTest.cs +++ b/Storage/Storage.Test/BaseTest.cs @@ -43,6 +43,24 @@ namespace Storage.Test { internal Account() : base("Account") { } } + internal class ObjectWithFile : LCObject { + internal LCFile File { + get => this["file"] as LCFile; + set { + this["file"] = value; + } + } + + internal LCUser Owner { + get => this["owner"] as LCUser; + set { + this["owner"] = value; + } + } + + internal ObjectWithFile() : base("ObjectWithFile") {} + } + public class BaseTest { internal const string AppId = "ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz"; internal const string AppKey = "NUKmuRbdAhg1vrb2wexYo1jo"; @@ -59,6 +77,7 @@ namespace Storage.Test { LCObject.RegisterSubclass("Account", () => new Account()); LCObject.RegisterSubclass("Hello", () => new Hello()); LCObject.RegisterSubclass("World", () => new World()); + LCObject.RegisterSubclass("ObjectWithFile", () => new ObjectWithFile()); } [TearDown] diff --git a/Storage/Storage.Test/SubClassTest.cs b/Storage/Storage.Test/SubClassTest.cs index 6a48082..6cd73cf 100644 --- a/Storage/Storage.Test/SubClassTest.cs +++ b/Storage/Storage.Test/SubClassTest.cs @@ -34,5 +34,24 @@ namespace Storage.Test { await account.Save(); await account.Delete(); } + + [Test] + public async Task ObjectWithFile() { + LCUser user = await LCUser.Login("hello", "world"); + ObjectWithFile obj = new ObjectWithFile() { + File = new LCFile("avatar", "../../../../../assets/hello.png"), + Owner = user + }; + await obj.Save(); + + LCQuery query = new LCQuery("ObjectWithFile"); + ObjectWithFile obj2 = await query.Get(obj.ObjectId); + + TestContext.WriteLine(obj2.File.Url); + TestContext.WriteLine(obj2.Owner.ObjectId); + + Assert.IsNotNull(obj2.File.Url); + Assert.IsNotNull(obj2.Owner.ObjectId); + } } } diff --git a/Storage/Storage/Internal/Codec/LCDecoder.cs b/Storage/Storage/Internal/Codec/LCDecoder.cs index ec351ee..79402f8 100644 --- a/Storage/Storage/Internal/Codec/LCDecoder.cs +++ b/Storage/Storage/Internal/Codec/LCDecoder.cs @@ -13,14 +13,16 @@ namespace LeanCloud.Storage.Internal.Codec { return DecodeDate(dict); } else if (type == "Bytes") { return DecodeBytes(dict); - } else if (type == "Object") { + } else if (type == "Pointer") { return DecodeObject(dict); - } else if (type == "Pointer" || type == "Object") { + } else if (type == "Object") { return DecodeObject(dict); } else if (type == "Relation") { return DecodeRelation(dict); } else if (type == "GeoPoint") { return DecodeGeoPoint(dict); + } else if (type == "File") { + return DecodeFile(dict); } } Dictionary d = new Dictionary(); @@ -61,6 +63,13 @@ namespace LeanCloud.Storage.Internal.Codec { return obj; } + public static LCFile DecodeFile(IDictionary dict) { + LCFile file = new LCFile(); + LCObjectData objectData = LCObjectData.Decode(dict as Dictionary); + file.Merge(objectData); + return file; + } + public static LCRelation DecodeRelation(IDictionary dict) { LCRelation relation = new LCRelation(); relation.TargetClass = dict["className"].ToString(); diff --git a/Storage/Storage/Public/LCObject.cs b/Storage/Storage/Public/LCObject.cs index 62868ea..273163e 100644 --- a/Storage/Storage/Public/LCObject.cs +++ b/Storage/Storage/Public/LCObject.cs @@ -73,12 +73,8 @@ namespace LeanCloud.Storage { } } - bool isNew; - bool IsDirty { - get { - return isNew || estimatedData.Count > 0; - } + get; set; } /// @@ -96,7 +92,7 @@ namespace LeanCloud.Storage { operationDict = new Dictionary(); data.ClassName = className; - isNew = true; + IsDirty = true; } /// @@ -111,7 +107,7 @@ namespace LeanCloud.Storage { } LCObject obj = Create(className); obj.data.ObjectId = objectId; - obj.isNew = false; + obj.IsDirty = false; return obj; } @@ -327,8 +323,19 @@ namespace LeanCloud.Storage { static async Task SaveBatches(Stack batches) { while (batches.Count > 0) { LCBatch batch = batches.Pop(); + + // 特殊处理 File 依赖 + IEnumerable dirtyFiles = batch.objects.Where(item => (item is LCFile) && item.IsDirty) + .Cast(); + foreach (LCFile file in dirtyFiles) { + await file.Save(); + } + List dirtyObjects = batch.objects.Where(item => item.IsDirty) .ToList(); + if (dirtyObjects.Count == 0) { + continue; + } List> requestList = dirtyObjects.Select(item => { string path = item.ObjectId == null ? @@ -567,6 +574,7 @@ namespace LeanCloud.Storage { } else { operationDict[key] = op; } + IsDirty = true; } public void Merge(LCObjectData objectData) { @@ -587,7 +595,7 @@ namespace LeanCloud.Storage { RebuildEstimatedData(); // 清空操作 operationDict.Clear(); - isNew = false; + IsDirty = false; } void RebuildEstimatedData() {