* ObjectControllerTests.cs: chore: 简化遍历逻辑
* AVObject.cs: * AVQueryExtensions.cs: * AVEncoder.cs: * Conversion.cs:
parent
e5aa736805
commit
6c62ed2707
|
@ -1,4 +1,5 @@
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -66,10 +67,14 @@ namespace LeanCloud.Test {
|
||||||
obj["content"] = "batch object";
|
obj["content"] = "batch object";
|
||||||
objList.Add(obj);
|
objList.Add(obj);
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
await objList.SaveAllAsync();
|
await objList.SaveAllAsync();
|
||||||
objList.ForEach(obj => {
|
objList.ForEach(obj => {
|
||||||
Assert.NotNull(obj.ObjectId);
|
Assert.NotNull(obj.ObjectId);
|
||||||
});
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
TestContext.Out.WriteLine(e.Message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
|
@ -77,9 +77,6 @@ namespace LeanCloud.Storage.Internal {
|
||||||
private object EncodeList(IList<object> list) {
|
private object EncodeList(IList<object> list) {
|
||||||
List<object> newArray = new List<object>();
|
List<object> newArray = new List<object>();
|
||||||
foreach (object item in list) {
|
foreach (object item in list) {
|
||||||
if (!IsValidType(item)) {
|
|
||||||
throw new ArgumentException("Invalid type for value in an array");
|
|
||||||
}
|
|
||||||
newArray.Add(Encode(item));
|
newArray.Add(Encode(item));
|
||||||
}
|
}
|
||||||
return newArray;
|
return newArray;
|
||||||
|
|
|
@ -8,6 +8,7 @@ using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Linq;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
namespace LeanCloud {
|
namespace LeanCloud {
|
||||||
|
@ -436,8 +437,7 @@ string propertyName
|
||||||
/// <param name="traverseAVObjects">Whether to traverse into AVObjects' children</param>
|
/// <param name="traverseAVObjects">Whether to traverse into AVObjects' children</param>
|
||||||
/// <param name="yieldRoot">Whether to include the root in the result</param>
|
/// <param name="yieldRoot">Whether to include the root in the result</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal static IEnumerable<object> DeepTraversal(
|
internal static IEnumerable<object> DeepTraversal(object root, bool traverseAVObjects = false, bool yieldRoot = false) {
|
||||||
object root, bool traverseAVObjects = false, bool yieldRoot = false) {
|
|
||||||
var items = DeepTraversalInternal(root,
|
var items = DeepTraversalInternal(root,
|
||||||
traverseAVObjects,
|
traverseAVObjects,
|
||||||
new HashSet<object>(new IdentityEqualityComparer<object>()));
|
new HashSet<object>(new IdentityEqualityComparer<object>()));
|
||||||
|
@ -448,16 +448,12 @@ string propertyName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<object> DeepTraversalInternal(
|
private static IEnumerable<object> DeepTraversalInternal(object root, bool traverseAVObjects, ICollection<object> seen) {
|
||||||
object root, bool traverseAVObjects, ICollection<object> seen) {
|
|
||||||
seen.Add(root);
|
seen.Add(root);
|
||||||
var itemsToVisit = isCompiledByIL2CPP ? (System.Collections.IEnumerable)null : (IEnumerable<object>)null;
|
IEnumerable itemsToVisit = null;
|
||||||
var dict = Conversion.As<IDictionary<string, object>>(root);
|
if (root is IDictionary dict) {
|
||||||
if (dict != null) {
|
|
||||||
itemsToVisit = dict.Values;
|
itemsToVisit = dict.Values;
|
||||||
} else {
|
} else if (root is IList list) {
|
||||||
var list = Conversion.As<IList<object>>(root);
|
|
||||||
if (list != null) {
|
|
||||||
itemsToVisit = list;
|
itemsToVisit = list;
|
||||||
} else if (traverseAVObjects) {
|
} else if (traverseAVObjects) {
|
||||||
var obj = root as AVObject;
|
var obj = root as AVObject;
|
||||||
|
@ -465,7 +461,6 @@ string propertyName
|
||||||
itemsToVisit = obj.Keys.ToList().Select(k => obj[k]);
|
itemsToVisit = obj.Keys.ToList().Select(k => obj[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (itemsToVisit != null) {
|
if (itemsToVisit != null) {
|
||||||
foreach (var i in itemsToVisit) {
|
foreach (var i in itemsToVisit) {
|
||||||
if (!seen.Contains(i)) {
|
if (!seen.Contains(i)) {
|
||||||
|
@ -1104,11 +1099,6 @@ string propertyName
|
||||||
internal void Set(string key, object value) {
|
internal void Set(string key, object value) {
|
||||||
lock (mutex) {
|
lock (mutex) {
|
||||||
OnSettingValue(ref key, ref value);
|
OnSettingValue(ref key, ref value);
|
||||||
|
|
||||||
if (!AVEncoder.IsValidType(value)) {
|
|
||||||
throw new ArgumentException("Invalid type for value: " + value.GetType().ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
PerformOperation(key, new AVSetOperation(value));
|
PerformOperation(key, new AVSetOperation(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -556,12 +556,6 @@ namespace LeanCloud
|
||||||
var fieldPath = GetValue(leftTransformed.Arguments[0]) as string;
|
var fieldPath = GetValue(leftTransformed.Arguments[0]) as string;
|
||||||
var filterValue = GetValue(node.Right);
|
var filterValue = GetValue(node.Right);
|
||||||
|
|
||||||
if (filterValue != null && !AVEncoder.IsValidType(filterValue))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(
|
|
||||||
"Where clauses must use types compatible with AVObjects.");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (node.NodeType)
|
switch (node.NodeType)
|
||||||
{
|
{
|
||||||
case ExpressionType.GreaterThan:
|
case ExpressionType.GreaterThan:
|
||||||
|
|
|
@ -61,42 +61,6 @@ namespace LeanCloud.Utilities
|
||||||
return (T)Convert.ChangeType(value, typeof(T));
|
return (T)Convert.ChangeType(value, typeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ReflectionHelpers.IsConstructedGenericType(typeof(T)))
|
|
||||||
{
|
|
||||||
// Add lifting for nullables. Only supports conversions between primitives.
|
|
||||||
if (ReflectionHelpers.IsNullable(typeof(T)))
|
|
||||||
{
|
|
||||||
var innerType = ReflectionHelpers.GetGenericTypeArguments(typeof(T))[0];
|
|
||||||
if (ReflectionHelpers.IsPrimitive(innerType))
|
|
||||||
{
|
|
||||||
return (T)Convert.ChangeType(value, innerType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Type listType = GetInterfaceType(value.GetType(), typeof(IList<>));
|
|
||||||
var la = typeof(T).GetGenericTypeDefinition();
|
|
||||||
var ilb = typeof(IList<>);
|
|
||||||
var lb = typeof(List<>);
|
|
||||||
if (listType != null &&
|
|
||||||
(la == ilb || la == lb))
|
|
||||||
{
|
|
||||||
var wrapperType = typeof(FlexibleListWrapper<,>)
|
|
||||||
.MakeGenericType(ReflectionHelpers.GetGenericTypeArguments(typeof(T))[0],
|
|
||||||
ReflectionHelpers.GetGenericTypeArguments(listType)[0]);
|
|
||||||
return Activator.CreateInstance(wrapperType, value);
|
|
||||||
}
|
|
||||||
Type dictType = GetInterfaceType(value.GetType(), typeof(IDictionary<,>));
|
|
||||||
var da = typeof(T).GetGenericTypeDefinition();
|
|
||||||
var db = typeof(IDictionary<,>);
|
|
||||||
if (dictType != null &&
|
|
||||||
da == db)
|
|
||||||
{
|
|
||||||
var wrapperType = typeof(FlexibleDictionaryWrapper<,>)
|
|
||||||
.MakeGenericType(ReflectionHelpers.GetGenericTypeArguments(typeof(T))[1],
|
|
||||||
ReflectionHelpers.GetGenericTypeArguments(dictType)[1]);
|
|
||||||
return Activator.CreateInstance(wrapperType, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue