* RelationTest.cs: chore: 完善 Relation 和 Role 的功能和测试

* LCRole.cs:
* LCObject.cs:
* LCRelation.cs:
* RoleTest.cs:
* LCDecoder.cs:
* LCEncoder.cs:
* LCAddRelationOperation.cs:
* LCRemoveRelationOperation.cs:
oneRain 2020-02-27 12:31:48 +08:00
parent 6576cbd47f
commit 83ad15a8ec
9 changed files with 189 additions and 51 deletions

View File

@ -1,46 +1,66 @@
using NUnit.Framework; using NUnit.Framework;
using LeanCloud;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using LeanCloud.Storage;
namespace LeanCloud.Test { namespace LeanCloud.Test {
public class RelationTest { public class RelationTest {
[SetUp] [SetUp]
public void SetUp() { public void SetUp() {
Utils.InitNorthChina(); Logger.LogDelegate += Utils.Print;
LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com");
}
[TearDown]
public void TearDown() {
Logger.LogDelegate -= Utils.Print;
} }
[Test] [Test]
public async Task CreateRelation() { public async Task AddAndRemove() {
AVObject tag1 = new AVObject("Tag") { LCObject parent = new LCObject("Parent");
["name"] = "hello" LCObject c1 = new LCObject("Child");
}; parent.AddRelation("children", c1);
await tag1.SaveAsync(); LCObject c2 = new LCObject("Child");
AVObject tag2 = new AVObject("Tag") { parent.AddRelation("children", c2);
{ "name", "world" } await parent.Save();
};
await tag2.SaveAsync(); LCRelation<LCObject> relation = parent["children"] as LCRelation<LCObject>;
AVObject todo = new AVObject("Todo"); LCQuery<LCObject> query = relation.Query;
AVRelation<AVObject> relation = todo.GetRelation<AVObject>("tags"); int count = await query.Count();
relation.Add(tag1);
relation.Add(tag2); TestContext.WriteLine($"count: {count}");
await todo.SaveAsync(); Assert.AreEqual(count, 2);
parent.RemoveRelation("children", c2);
await parent.Save();
int count2 = await query.Count();
TestContext.WriteLine($"count: {count2}");
Assert.AreEqual(count2, 1);
} }
[Test] [Test]
public async Task QueryRelation() { public async Task Query() {
AVQuery<AVObject> query = new AVQuery<AVObject>("Todo"); LCQuery<LCObject> query = new LCQuery<LCObject>("Parent");
query.OrderByDescending("createdAt"); LCObject parent = await query.Get("5e13112021b47e0070ed0922");
AVObject todo = await query.FirstAsync(); LCRelation<LCObject> relation = parent["children"] as LCRelation<LCObject>;
AVRelation<AVObject> relation = todo.GetRelation<AVObject>("tags");
AVQuery<AVObject> tagQuery = relation.Query; TestContext.WriteLine(relation.Key);
IEnumerable<AVObject> tags = await tagQuery.FindAsync(); TestContext.WriteLine(relation.Parent);
Assert.Greater(tags.Count(), 0); TestContext.WriteLine(relation.TargetClass);
TestContext.Out.WriteLine($"count: {tags.Count()}");
foreach (AVObject tag in tags) { Assert.NotNull(relation.Key);
TestContext.Out.WriteLine($"{tag.ObjectId}, {tag["name"]}"); Assert.NotNull(relation.Parent);
} Assert.NotNull(relation.TargetClass);
LCQuery<LCObject> relationQuery = relation.Query;
List<LCObject> list = await relationQuery.Find();
list.ForEach(item => {
TestContext.WriteLine(item.ObjectId);
Assert.NotNull(item.ObjectId);
});
} }
} }
} }

View File

@ -1,28 +1,49 @@
using NUnit.Framework; using NUnit.Framework;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using LeanCloud; using System.Linq;
using LeanCloud.Storage;
namespace LeanCloud.Test { namespace LeanCloud.Test {
[TestFixture] [TestFixture]
public class RoleTest { public class RoleTest {
[SetUp] [SetUp]
public void SetUp() { public void SetUp() {
Utils.InitNorthChina(true); Logger.LogDelegate += Utils.Print;
LeanCloud.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com");
}
[TearDown]
public void TearDown() {
Logger.LogDelegate -= Utils.Print;
} }
[Test] [Test]
public async Task GetUsersFromRole() { public async Task NewRole() {
AVQuery<AVRole> query = new AVQuery<AVRole>(); LCUser currentUser = await LCUser.Login("game", "play");
AVRole role = await query.FirstAsync(); LCACL acl = new LCACL();
AVQuery<AVUser> userQuery = role.Users.Query; acl.PublicReadAccess = true;
IEnumerable<AVUser> users = await userQuery.FindAsync(); acl.SetUserWriteAccess(currentUser, true);
Assert.Greater(users.Count(), 0); string name = $"role_{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}";
TestContext.Out.WriteLine($"count: {users.Count()}"); LCRole role = LCRole.Create(name, acl);
foreach (AVUser user in users) { role.AddRelation("users", currentUser);
TestContext.Out.WriteLine($"{user.ObjectId}, {user.Username}"); await role.Save();
} }
[Test]
public async Task Query() {
LCQuery<LCRole> query = LCRole.GetQuery();
List<LCRole> list = await query.Find();
list.ForEach(item => {
TestContext.WriteLine($"{item.ObjectId} : {item.Name}");
Assert.NotNull(item.ObjectId);
Assert.NotNull(item.Name);
TestContext.WriteLine(item.Roles.GetType());
TestContext.WriteLine(item.Users.GetType());
Assert.IsTrue(item.Roles is LCRelation<LCRole>);
Assert.IsTrue(item.Users is LCRelation<LCUser>);
});
} }
} }
} }

View File

@ -63,7 +63,7 @@ namespace LeanCloud.Storage.Internal.Codec {
static LCRelation<LCObject> DecodeRelation(IDictionary dict) { static LCRelation<LCObject> DecodeRelation(IDictionary dict) {
LCRelation<LCObject> relation = new LCRelation<LCObject>(); LCRelation<LCObject> relation = new LCRelation<LCObject>();
relation.targetClass = dict["className"].ToString(); relation.TargetClass = dict["className"].ToString();
return relation; return relation;
} }

View File

@ -100,7 +100,7 @@ namespace LeanCloud.Storage.Internal.Codec {
static object EncodeRelation(LCRelation<LCObject> relation) { static object EncodeRelation(LCRelation<LCObject> relation) {
return new Dictionary<string, object> { return new Dictionary<string, object> {
{ "__type", "Relation" }, { "__type", "Relation" },
{ "className", relation.targetClass } { "className", relation.TargetClass }
}; };
} }

View File

@ -32,7 +32,7 @@ namespace LeanCloud.Storage.Internal.Operation {
public object Apply(object oldValue, string key) { public object Apply(object oldValue, string key) {
LCRelation<LCObject> relation = new LCRelation<LCObject>(); LCRelation<LCObject> relation = new LCRelation<LCObject>();
relation.targetClass = valueList[0].ClassName; relation.TargetClass = valueList[0].ClassName;
return relation; return relation;
} }

View File

@ -31,7 +31,7 @@ namespace LeanCloud.Storage.Internal.Operation {
public object Apply(object oldValue, string key) { public object Apply(object oldValue, string key) {
LCRelation<LCObject> relation = new LCRelation<LCObject>(); LCRelation<LCObject> relation = new LCRelation<LCObject>();
relation.targetClass = valueList[0].ClassName; relation.TargetClass = valueList[0].ClassName;
return relation; return relation;
} }

View File

@ -140,6 +140,28 @@ namespace LeanCloud.Storage {
ApplyOperation(key, deleteOp); ApplyOperation(key, deleteOp);
} }
public void AddRelation(string key, LCObject value) {
if (string.IsNullOrEmpty(key)) {
throw new ArgumentNullException(nameof(key));
}
if (value == null) {
throw new ArgumentNullException(nameof(value));
}
LCAddRelationOperation op = new LCAddRelationOperation(new List<LCObject> { value });
ApplyOperation(key, op);
}
public void RemoveRelation(string key, LCObject value) {
if (string.IsNullOrEmpty(key)) {
throw new ArgumentNullException(nameof(key));
}
if (value == null) {
throw new ArgumentNullException(nameof(value));
}
LCRemoveRelationOperation op = new LCRemoveRelationOperation(value);
ApplyOperation(key, op);
}
static async Task SaveBatches(Stack<LCBatch> batches) { static async Task SaveBatches(Stack<LCBatch> batches) {
while (batches.Count > 0) { while (batches.Count > 0) {
LCBatch batch = batches.Pop(); LCBatch batch = batches.Pop();

View File

@ -1,20 +1,41 @@
using System; /// <summary>
/// 关系类
/// </summary>
namespace LeanCloud.Storage { namespace LeanCloud.Storage {
public class LCRelation<T> where T : LCObject { public class LCRelation<T> where T : LCObject {
/// <summary>
/// 字段名
/// </summary>
public string Key { public string Key {
get; set; get; set;
} }
/// <summary>
/// 父对象
/// </summary>
public LCObject Parent { public LCObject Parent {
get; set; get; set;
} }
public string targetClass { /// <summary>
/// 关联类型名
/// </summary>
public string TargetClass {
get; set; get; set;
} }
public LCRelation() { public LCRelation() {
} }
/// <summary>
/// 获取 Relation 的查询对象
/// </summary>
public LCQuery<T> Query {
get {
LCQuery<T> query = new LCQuery<T>(TargetClass);
query.WhereRelatedTo(Parent, Key);
return query;
}
}
} }
} }

View File

@ -1,10 +1,64 @@
using System; namespace LeanCloud.Storage {
/// <summary>
namespace LeanCloud.Storage { /// 角色
/// </summary>
public class LCRole : LCObject { public class LCRole : LCObject {
public const string CLASS_NAME = "_Role"; public const string CLASS_NAME = "_Role";
/// <summary>
/// 名字
/// </summary>
public string Name {
get {
return this["name"] as string;
} set {
this["name"] = value;
}
}
/// <summary>
/// 关联角色
/// </summary>
public LCRelation<LCRole> Roles {
get {
LCRelation<LCObject> roles = this["roles"] as LCRelation<LCObject>;
return new LCRelation<LCRole> {
Parent = roles.Parent,
Key = "roles"
};
}
}
/// <summary>
/// 关联用户
/// </summary>
public LCRelation<LCUser> Users {
get {
LCRelation<LCObject> users = this["users"] as LCRelation<LCObject>;
return new LCRelation<LCUser> {
Parent = users.Parent,
Key = "users"
};
}
}
public LCRole() : base(CLASS_NAME) { public LCRole() : base(CLASS_NAME) {
} }
public static LCRole Create(string name, LCACL acl) {
LCRole role = new LCRole() {
Name = name,
ACL = acl
};
return role;
}
/// <summary>
/// 获取角色查询对象
/// </summary>
/// <returns></returns>
public static LCQuery<LCRole> GetQuery() {
return new LCQuery<LCRole>(CLASS_NAME);
}
} }
} }