mirror of
https://github.com/dotnetcore/BootstrapBlazor.git
synced 2025-12-19 09:56:41 +08:00
feat(QueryPageOptions): SearchModel support serialize (#7327)
* refactor: 代码重构增加 type 标识类型 * test: 更新单元测试 * test: 补充单元测试 * test: 增加单元测试提高覆盖率 * chore: bump version 10.1.4-beta07
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>10.1.3</Version>
|
||||
<Version>10.1.4-beta07</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -42,11 +42,7 @@ public sealed class JsonFilterKeyValueActionConverter : JsonConverter<FilterKeyV
|
||||
action.FieldKey = reader.GetString();
|
||||
break;
|
||||
case "fieldValueType":
|
||||
var typeName = reader.GetString();
|
||||
if (!string.IsNullOrEmpty(typeName))
|
||||
{
|
||||
fieldValueType = Type.GetType(typeName);
|
||||
}
|
||||
fieldValueType = TypeExtensions.GetSafeType(reader.GetString());
|
||||
break;
|
||||
case "fieldValue":
|
||||
if (fieldValueType != null)
|
||||
@@ -89,7 +85,7 @@ public sealed class JsonFilterKeyValueActionConverter : JsonConverter<FilterKeyV
|
||||
writer.WriteStartObject();
|
||||
writer.WriteString("fieldKey", value.FieldKey);
|
||||
|
||||
writer.WriteString("fieldValueType", value.FieldValue?.GetType().FullName);
|
||||
WriteFieldValueType(writer, value, options);
|
||||
|
||||
writer.WritePropertyName("fieldValue");
|
||||
writer.WriteRawValue(JsonSerializer.Serialize(value.FieldValue, options));
|
||||
@@ -109,4 +105,13 @@ public sealed class JsonFilterKeyValueActionConverter : JsonConverter<FilterKeyV
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
private static void WriteFieldValueType(Utf8JsonWriter writer, FilterKeyValueAction value, JsonSerializerOptions options)
|
||||
{
|
||||
if (value.FieldValue != null)
|
||||
{
|
||||
var type = value.FieldValue.GetType();
|
||||
writer.WriteString("fieldValueType", type.AssemblyQualifiedName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,11 +73,7 @@ public sealed class JsonQueryPageOptionsConverter : JsonConverter<QueryPageOptio
|
||||
else if (propertyName == "searchModel")
|
||||
{
|
||||
reader.Read();
|
||||
var val = JsonSerializer.Deserialize<object>(ref reader, options);
|
||||
if (val != null)
|
||||
{
|
||||
ret.SearchModel = val;
|
||||
}
|
||||
ReadSearchModel(ref reader, ret, options);
|
||||
}
|
||||
else if (propertyName == "pageIndex")
|
||||
{
|
||||
@@ -229,8 +225,7 @@ public sealed class JsonQueryPageOptionsConverter : JsonConverter<QueryPageOptio
|
||||
}
|
||||
if (value.SearchModel != null)
|
||||
{
|
||||
writer.WritePropertyName("searchModel");
|
||||
writer.WriteRawValue(JsonSerializer.Serialize(value.SearchModel, options));
|
||||
WriteSearchModel(writer, value.SearchModel, options);
|
||||
}
|
||||
if (value.PageIndex > 1)
|
||||
{
|
||||
@@ -302,4 +297,52 @@ public sealed class JsonQueryPageOptionsConverter : JsonConverter<QueryPageOptio
|
||||
}
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
private static void WriteSearchModel(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStartObject("searchModel");
|
||||
writer.WriteString("type", value.GetType().AssemblyQualifiedName);
|
||||
writer.WritePropertyName("value");
|
||||
writer.WriteRawValue(JsonSerializer.Serialize(value, options));
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
private static void ReadSearchModel(ref Utf8JsonReader reader, QueryPageOptions value, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.StartObject)
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.EndObject)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (reader.TokenType == JsonTokenType.PropertyName)
|
||||
{
|
||||
var propertyName = reader.GetString();
|
||||
if (propertyName == "type")
|
||||
{
|
||||
reader.Read();
|
||||
Type? type = TypeExtensions.GetSafeType(reader.GetString());
|
||||
|
||||
reader.Read();
|
||||
propertyName = reader.GetString();
|
||||
if (propertyName == "value")
|
||||
{
|
||||
reader.Read();
|
||||
if (type != null)
|
||||
{
|
||||
value.SearchModel = JsonSerializer.Deserialize(ref reader, type, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
value.SearchModel = JsonSerializer.Deserialize<object>(ref reader, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License
|
||||
// See the LICENSE file in the project root for more information.
|
||||
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
|
||||
@@ -64,4 +64,20 @@ internal static class TypeExtensions
|
||||
public static string GetUniqueTypeName(this Type type) => type.IsCollectible
|
||||
? $"{type.FullName}-{type.TypeHandle.Value}"
|
||||
: $"{type.FullName}";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 通过 typeName 参数安全获取 Type 实例
|
||||
/// </summary>
|
||||
/// <param name="typeName"></param>
|
||||
/// <returns></returns>
|
||||
public static Type? GetSafeType(string? typeName)
|
||||
{
|
||||
Type? type = null;
|
||||
if (!string.IsNullOrEmpty(typeName))
|
||||
{
|
||||
type = Type.GetType(typeName, throwOnError: false);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ public class QueryPageOptionsExtensionsTest : BootstrapBlazorTestBase
|
||||
IsTriggerByPagination = true,
|
||||
IsPage = true,
|
||||
IsVirtualScroll = true,
|
||||
SearchModel = new { Name = "Test1", Count = 2 }
|
||||
SearchModel = new Foo { Name = "Test1", Count = 2 }
|
||||
};
|
||||
|
||||
model.Filters.Add(cut.Instance);
|
||||
@@ -196,6 +196,11 @@ public class QueryPageOptionsExtensionsTest : BootstrapBlazorTestBase
|
||||
var expected = JsonSerializer.Deserialize<QueryPageOptions>(payload);
|
||||
Assert.NotNull(expected);
|
||||
Assert.Equal("SearchText", expected.SearchText);
|
||||
|
||||
var foo = expected.SearchModel as Foo;
|
||||
Assert.NotNull(foo);
|
||||
Assert.Equal("Test1", foo.Name);
|
||||
|
||||
Assert.Equal("Name1", expected.SortName);
|
||||
Assert.Equal(3, expected.StartIndex);
|
||||
Assert.Equal(4, expected.PageIndex);
|
||||
@@ -216,6 +221,73 @@ public class QueryPageOptionsExtensionsTest : BootstrapBlazorTestBase
|
||||
Assert.Equal(2, expected.AdvancedSortList.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SearchModel_Serialize()
|
||||
{
|
||||
var model = new QueryPageOptions
|
||||
{
|
||||
SearchModel = new { Name = "Test1", Count = 2 }
|
||||
};
|
||||
var payload = JsonSerializer.Serialize(model);
|
||||
var expected = JsonSerializer.Deserialize<QueryPageOptions>(payload);
|
||||
|
||||
Assert.NotNull(expected);
|
||||
Assert.NotNull(expected.SearchModel);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SearchModel_Serialize_TableSearchModel()
|
||||
{
|
||||
var model = new QueryPageOptions
|
||||
{
|
||||
SearchModel = new FooSearchModel { Name = "Test1" }
|
||||
};
|
||||
var payload = JsonSerializer.Serialize(model);
|
||||
var expected = JsonSerializer.Deserialize<QueryPageOptions>(payload);
|
||||
|
||||
Assert.NotNull(expected);
|
||||
Assert.NotNull(expected.SearchModel);
|
||||
Assert.Equal("FooSearchModel", expected.SearchModel.GetType().Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SearchModel_Serialize_NullType()
|
||||
{
|
||||
var model = new QueryPageOptions
|
||||
{
|
||||
SearchModel = new FooSearchModel { Name = "Test1" }
|
||||
};
|
||||
var payload = JsonSerializer.Serialize(model);
|
||||
|
||||
// 更改为错误的类型
|
||||
payload = payload.Replace("FooSearchModel", "FooSearchModel1");
|
||||
var expected = JsonSerializer.Deserialize<QueryPageOptions>(payload);
|
||||
|
||||
Assert.NotNull(expected);
|
||||
Assert.NotNull(expected.SearchModel);
|
||||
Assert.Equal("JsonElement", expected.SearchModel.GetType().Name);
|
||||
}
|
||||
|
||||
private class FooSearchModel : ITableSearchModel
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
|
||||
public IEnumerable<IFilterAction> GetSearches()
|
||||
{
|
||||
var ret = new List<IFilterAction>();
|
||||
if (!string.IsNullOrEmpty(Name))
|
||||
{
|
||||
ret.Add(new SearchFilterAction(nameof(Foo.Name), Name));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Name = null;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SerializeFilterAction_Ok()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user