From 4cfd99f9721380d36da2e572ce3747ce42571919 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Tue, 30 Dec 2025 15:50:57 +0800 Subject: [PATCH 1/6] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Extensions/LambadaExtensionsTest.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/test/UnitTest/Extensions/LambadaExtensionsTest.cs b/test/UnitTest/Extensions/LambadaExtensionsTest.cs index e755a68b68e..5eb467f57bd 100644 --- a/test/UnitTest/Extensions/LambadaExtensionsTest.cs +++ b/test/UnitTest/Extensions/LambadaExtensionsTest.cs @@ -694,11 +694,6 @@ public override FilterKeyValueAction GetFilterConditions() } } - /// - /// - /// - /// - /// private class CustomDynamicData(Dictionary data) : System.Dynamic.DynamicObject { /// @@ -719,9 +714,9 @@ public CustomDynamicData() : this([]) { } /// public override bool TryGetMember(GetMemberBinder binder, out object? result) { - if (Dynamic.ContainsKey(binder.Name)) + if (Dynamic.TryGetValue(binder.Name, out string? value)) { - result = Dynamic[binder.Name]; + result = value; } else { From a535df096b405f5218adc76469bacc3a2aa5c5a5 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Tue, 30 Dec 2025 15:51:15 +0800 Subject: [PATCH 2/6] =?UTF-8?q?refactor:=20=E5=A2=9E=E5=8A=A0=E5=BF=BD?= =?UTF-8?q?=E7=95=A5=E5=A4=A7=E5=B0=8F=E5=86=99=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extensions/LambdaExtensions.cs | 58 ++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/src/BootstrapBlazor/Extensions/LambdaExtensions.cs b/src/BootstrapBlazor/Extensions/LambdaExtensions.cs index ec7cd250343..9433ffe8367 100644 --- a/src/BootstrapBlazor/Extensions/LambdaExtensions.cs +++ b/src/BootstrapBlazor/Extensions/LambdaExtensions.cs @@ -34,27 +34,27 @@ private class ComboExpressionVisitor(ParameterExpression parameter) : Expression /// /// /// - /// - public static Func GetFilterFunc(this FilterKeyValueAction filter) => filter.GetFilterLambda().Compile(); + /// 实例,此方法不支持 EFCore Where 查询 + public static Func GetFilterFunc(this FilterKeyValueAction filter, StringComparison? comparison = null) => filter.GetFilterLambda(comparison).Compile(); /// /// 指定 FilterKeyValueAction 获取 Lambda 表达式 /// /// /// - /// - public static Expression> GetFilterLambda(this FilterKeyValueAction filter) + /// 实例,此方法不支持 EFCore Where 查询 + public static Expression> GetFilterLambda(this FilterKeyValueAction filter, StringComparison? comparison = null) { var express = new List>>(); if (filter.Filters.Count > 0) { express.AddRange(filter.Filters.Select(f => f.Filters.Count > 0 - ? f.Filters.GetFilterLambda(f.FilterLogic) - : f.GetInnerFilterLambda())); + ? f.Filters.GetFilterLambda(f.FilterLogic, comparison) + : f.GetInnerFilterLambda(comparison))); } else { - express.Add(filter.GetInnerFilterLambda()); + express.Add(filter.GetInnerFilterLambda(comparison)); } return express.ExpressionAndLambda(filter.FilterLogic); } @@ -83,12 +83,13 @@ public static Expression> GetFilterLambda(this FilterKe /// /// /// + /// 实例 /// - private static Expression> GetFilterLambda(this IEnumerable filters, FilterLogic logic) + private static Expression> GetFilterLambda(this IEnumerable filters, FilterLogic logic, StringComparison? comparison = null) { var express = filters.Select(filter => filter.Filters.Count > 0 - ? filter.Filters.GetFilterLambda(filter.FilterLogic) - : filter.GetInnerFilterLambda()) + ? filter.Filters.GetFilterLambda(filter.FilterLogic, comparison) + : filter.GetInnerFilterLambda(comparison)) .ToList(); return express.ExpressionAndLambda(logic); } @@ -126,13 +127,7 @@ private static Expression> ExpressionAndLambda(this IEn return ret ?? (r => true); } - /// - /// 指定 FilterKeyValueAction 获取 Lambda 表达式 - /// - /// - /// - /// - private static Expression> GetInnerFilterLambda(this FilterKeyValueAction filter) + private static Expression> GetInnerFilterLambda(this FilterKeyValueAction filter, StringComparison? comparison = null) { Expression> ret = t => true; var type = typeof(TItem); @@ -148,7 +143,7 @@ Expression> GetSimpleFilterExpression() var prop = typeof(TItem).GetPropertyByName(filter.FieldKey) ?? throw new InvalidOperationException($"the model {type.Name} not found the property {filter.FieldKey}"); var parameter = Expression.Parameter(type); var fieldExpression = Expression.Property(parameter, prop); - ret = filter.GetFilterExpression(prop, fieldExpression, parameter); + ret = filter.GetFilterExpression(prop, fieldExpression, parameter, comparison); return ret; } @@ -175,13 +170,13 @@ Expression> GetComplexFilterExpression() if (fieldExpression != null) { - ret = filter.GetFilterExpression(prop, fieldExpression, parameter); + ret = filter.GetFilterExpression(prop, fieldExpression, parameter, comparison); } return ret; } } - private static Expression> GetFilterExpression(this FilterKeyValueAction filter, PropertyInfo? prop, Expression fieldExpression, ParameterExpression parameter) + private static Expression> GetFilterExpression(this FilterKeyValueAction filter, PropertyInfo? prop, Expression fieldExpression, ParameterExpression parameter, StringComparison? comparison = null) { var isNullable = false; var eq = fieldExpression; @@ -201,12 +196,12 @@ private static Expression> GetFilterExpression(this Fil } } eq = isNullable - ? Expression.AndAlso(Expression.NotEqual(fieldExpression, Expression.Constant(null)), filter.GetExpression(eq)) - : filter.GetExpression(eq); + ? Expression.AndAlso(Expression.NotEqual(fieldExpression, Expression.Constant(null)), filter.GetExpression(eq, comparison)) + : filter.GetExpression(eq, comparison); return Expression.Lambda>(eq, parameter); } - private static Expression GetExpression(this FilterKeyValueAction filter, Expression left) + private static Expression GetExpression(this FilterKeyValueAction filter, Expression left, StringComparison? comparison = null) { var right = Expression.Constant(filter.FieldValue); return filter.FilterAction switch @@ -217,8 +212,8 @@ private static Expression GetExpression(this FilterKeyValueAction filter, Expres FilterAction.GreaterThanOrEqual => Expression.GreaterThanOrEqual(left, right), FilterAction.LessThan => Expression.LessThan(left, right), FilterAction.LessThanOrEqual => Expression.LessThanOrEqual(left, right), - FilterAction.Contains => left.Contains(right), - FilterAction.NotContains => Expression.Not(left.Contains(right)), + FilterAction.Contains => left.Contains(right, comparison), + FilterAction.NotContains => Expression.Not(left.Contains(right, comparison)), _ => filter.FieldValue switch { LambdaExpression t => Expression.Invoke(t, left), @@ -228,12 +223,23 @@ private static Expression GetExpression(this FilterKeyValueAction filter, Expres }; } - private static BinaryExpression Contains(this Expression left, Expression right) + private static BinaryExpression Contains(this Expression left, Expression right, StringComparison? comparison) => comparison.HasValue + ? ContainsWidthComparison(left, right, comparison.Value) + : ContainsWithoutComparison(left, right); + + private static BinaryExpression ContainsWithoutComparison(this Expression left, Expression right) { var method = typeof(string).GetMethod("Contains", [typeof(string)])!; return Expression.AndAlso(Expression.NotEqual(left, Expression.Constant(null)), Expression.Call(left, method, right)); } + private static BinaryExpression ContainsWidthComparison(this Expression left, Expression right, StringComparison comparison) + { + var method = typeof(string).GetMethod("Contains", [typeof(string), typeof(StringComparison)])!; + var comparisonConstant = Expression.Constant(comparison); + return Expression.AndAlso(Expression.NotEqual(left, Expression.Constant(null)), Expression.Call(left, method, right, comparisonConstant)); + } + #region Count /// /// Count 方法内部使用 Lambda 表达式做通用适配 可接受 IEnumerable 与 Array 子类 From c9663fca0977152023a8b4566b08407386c2cc19 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Tue, 30 Dec 2025 16:00:48 +0800 Subject: [PATCH 3/6] refactor: add StringComparison parameter --- .../Extensions/QueryPageOptionsExtensions.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/BootstrapBlazor/Extensions/QueryPageOptionsExtensions.cs b/src/BootstrapBlazor/Extensions/QueryPageOptionsExtensions.cs index cf3c52ce585..da3346c2fbc 100644 --- a/src/BootstrapBlazor/Extensions/QueryPageOptionsExtensions.cs +++ b/src/BootstrapBlazor/Extensions/QueryPageOptionsExtensions.cs @@ -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 @@ -56,15 +56,17 @@ public static FilterKeyValueAction ToFilter(this QueryPageOptions option) /// 将 QueryPageOptions 过滤条件转换为 where 条件中的参数 "/> 推荐 Linq 使用 /// /// + /// 实例,此方法不支持 EFCore Where 查询 /// - public static Func ToFilterFunc(this QueryPageOptions option) => option.ToFilterLambda().Compile(); + public static Func ToFilterFunc(this QueryPageOptions option, StringComparison? comparison = null) => option.ToFilterLambda(comparison).Compile(); /// /// 将 QueryPageOptions 过滤条件转换为 表达式"/> 推荐 EFCore 使用 /// /// + /// 实例,此方法不支持 EFCore Where 查询 /// - public static Expression> ToFilterLambda(this QueryPageOptions option) => option.ToFilter().GetFilterLambda(); + public static Expression> ToFilterLambda(this QueryPageOptions option, StringComparison? comparison = null) => option.ToFilter().GetFilterLambda(comparison); /// /// 是否包含过滤条件 From 8cb296ead3d3db532b5acb2c4f6878d5946d49d0 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Tue, 30 Dec 2025 16:01:00 +0800 Subject: [PATCH 4/6] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extensions/LambadaExtensionsTest.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/UnitTest/Extensions/LambadaExtensionsTest.cs b/test/UnitTest/Extensions/LambadaExtensionsTest.cs index 5eb467f57bd..e326c618d34 100644 --- a/test/UnitTest/Extensions/LambadaExtensionsTest.cs +++ b/test/UnitTest/Extensions/LambadaExtensionsTest.cs @@ -12,6 +12,30 @@ namespace UnitTest.Extensions; public class LambadaExtensionsTest : BootstrapBlazorTestBase { + [Fact] + public void GetFilterFunc_Comparison() + { + var filter = new FilterKeyValueAction() + { + FieldKey = "Name", + FilterAction = FilterAction.Contains, + FieldValue = "T" + }; + + var foos = new Foo[] + { + new() { Name = "Test1" }, + new() { Name = "test2" }, + }; + + var items = foos.Where(filter.GetFilterFunc()); + Assert.Single(items); + + // 忽略大小写 + items = foos.Where(filter.GetFilterFunc(StringComparison.OrdinalIgnoreCase)); + Assert.Equal(2, items.Count()); + } + [Fact] public void GetFilterFunc_Null() { From b0b5dc287eaf1bb76998ccbeac0011cf54a480c5 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Tue, 30 Dec 2025 16:08:26 +0800 Subject: [PATCH 5/6] =?UTF-8?q?test:=20=E5=A2=9E=E5=8A=A0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs b/test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs index 6cec1d3537f..7f8ac62c93a 100644 --- a/test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs +++ b/test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs @@ -39,6 +39,11 @@ public void ToFilter_Searches() expected = _foos.Where(predicate); Assert.Equal(2, expected.Count()); + // 忽略大小写 + predicate = option.ToFilterFunc(StringComparison.OrdinalIgnoreCase); + expected = _foos.Where(predicate); + Assert.Equal(4, expected.Count()); + option.Searches.Clear(); option.Searches.Add(new SearchFilterAction("Name", "Mock")); predicate = option.ToFilterFunc(); From e874cf0da4ded891bd3df470a24b51e14b18b646 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Tue, 30 Dec 2025 16:13:22 +0800 Subject: [PATCH 6/6] chore: bump version 10.2.1-beta01 --- src/BootstrapBlazor/BootstrapBlazor.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index 18c20cc24fa..4f7144f245e 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@  - 10.2.0 + 10.2.1-beta01