Skip to content

Commit 115dacd

Browse files
committed
优化过滤器配置方式
1 parent 015632f commit 115dacd

File tree

9 files changed

+354
-273
lines changed

9 files changed

+354
-273
lines changed

Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</PropertyGroup>
1313

1414
<PropertyGroup>
15-
<Version>1.0.0-preview-001</Version>
15+
<Version>1.0.0-preview-002</Version>
1616

1717
<Description>An extension library for `EntityFrameworkCore` to support dynamic global filters. 一个 `EntityFrameworkCore` 的拓展库,用于支持动态的全局过滤器。</Description>
1818

@@ -24,7 +24,7 @@
2424
<RepositoryType>git</RepositoryType>
2525
<RepositoryUrl>$(PackageProjectUrl)</RepositoryUrl>
2626

27-
<PackageTags>entityframework entity-framework ef filter dynamicfilter dynamic-filter globalfilter global-filter</PackageTags>
27+
<PackageTags>entityframework entity-framework entityframeworkcore entity-framework-core ef efcore ef-core filter dynamicfilter dynamic-filter globalfilter global-filter</PackageTags>
2828
</PropertyGroup>
2929

3030
<ItemGroup Condition="'$(Configuration)' == 'Release'">

README.md

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33

44
An extension library for `EntityFrameworkCore` to support dynamic global filters. 一个 `EntityFrameworkCore` 的拓展库,用于支持动态的全局过滤器。
55

6-
- 动态全局过滤器支持;
6+
- 动态全局过滤器;
7+
- 支持自由组合多个过滤器;
78
- 全局过滤器支持排序与位置设置(针对联合索引场景,`EntityFrameworkCore``QueryFilter` 只能附加到查询头部,对联合索引不友好);
9+
- 支持查询时忽略部分过滤器;
810
- 目标框架 `net7.0`+;
911

1012
### NOTE!!!
@@ -33,22 +35,26 @@ services.AddDbContext<XXXXContext>((IServiceProvider serviceProvider, DbContextO
3335
```C#
3436
services.AddEntityFrameworkDynamicQueryFilter(options =>
3537
{
36-
//针对实体 User 添加头部表达式过滤器,表达式过滤器根据查询时 ServiceProvider 中的服务状态动态构造,表达式将在查询 User 时拼接到查询头部
37-
options.AddHeadFilter<User>(provider =>
38+
// 配置实体 User 的过滤器
39+
options.Entity<User>(builder =>
3840
{
39-
var currentTenant = provider.GetRequiredService<ICurrentTenant>();
40-
return currentTenant.Id is null
41-
? n => true
42-
: n => n.TenantId == currentTenant.Id;
41+
//添加头部表达式过滤器,表达式过滤器根据查询时 ServiceProvider 中的服务状态动态构造,表达式将在查询 User 时拼接到查询头部
42+
builder.AddHeadFilter(provider =>
43+
{
44+
var currentTenant = provider.GetRequiredService<ICurrentTenant>();
45+
return currentTenant.Id is null
46+
? n => true
47+
: n => n.TenantId == currentTenant.Id;
48+
});
49+
50+
//添加过滤器 MyQueryFilter(从DI容器中获取),其名称、位置、排序由 MyQueryFilter 内部确定
51+
builder.AddFilter<MyQueryFilter>();
52+
53+
//添加尾部表达式过滤器,其名称为 SoftDeletion,表达式将在查询 User 时拼接到查询末尾
54+
builder.AddTailFilter("SoftDeletion", n => n.IsDeleted == false);
55+
56+
//Other options
4357
});
44-
45-
//针对实体 User 添加过滤器 MyQueryFilter(从DI容器中获取),其名称、位置、排序由 MyQueryFilter 内部确定
46-
options.AddFilter<MyQueryFilter, User>();
47-
48-
//添加针对实体 User 的尾部表达式过滤器,其名称为 SoftDeletion,表达式将在查询 User 时拼接到查询末尾
49-
options.AddTailFilter<User>("SoftDeletion", n => n.IsDeleted == false);
50-
51-
//Other options
5258
});
5359
```
5460

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
using System.Linq.Expressions;
2+
using Microsoft.Extensions.DependencyInjection;
3+
4+
namespace Microsoft.EntityFrameworkCore.Extensions;
5+
6+
/// <summary>
7+
/// <typeparamref name="TEntity"/> 的动态过滤器构建器
8+
/// </summary>
9+
/// <typeparam name="TEntity"></typeparam>
10+
public class EntityDynamicFilterBuilder<TEntity>
11+
{
12+
#region Private 字段
13+
14+
private readonly EntityDynamicQueryFilterMetadata _metadata;
15+
16+
#endregion Private 字段
17+
18+
#region Public 构造函数
19+
20+
/// <inheritdoc cref="EntityDynamicFilterBuilder{TEntity}"/>
21+
public EntityDynamicFilterBuilder(EntityDynamicQueryFilterMetadata metadata)
22+
{
23+
_metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
24+
}
25+
26+
#endregion Public 构造函数
27+
28+
#region DelegationFilter
29+
30+
internal EntityDynamicFilterBuilder<TEntity> AddFilter(Func<IServiceProvider, IDynamicQueryFilter> queryFilterFactory)
31+
{
32+
_metadata.DynamicQueryFilterFactories.Add(queryFilterFactory);
33+
return this;
34+
}
35+
36+
#endregion DelegationFilter
37+
38+
#region InstanceFilter
39+
40+
/// <summary>
41+
/// 为实体 <typeparamref name="TEntity"/> 添加过滤器 <paramref name="queryFilter"/>
42+
/// </summary>
43+
/// <param name="queryFilter"></param>
44+
/// <returns></returns>
45+
public EntityDynamicFilterBuilder<TEntity> AddFilter(IDynamicQueryFilter<TEntity> queryFilter)
46+
{
47+
return AddFilter(_ => queryFilter);
48+
}
49+
50+
#endregion InstanceFilter
51+
52+
#region TypeFilter
53+
54+
/// <summary>
55+
/// 为实体 <typeparamref name="TEntity"/> 添加过滤器 <typeparamref name="TQueryFilter"/>
56+
/// </summary>
57+
/// <typeparam name="TQueryFilter"></typeparam>
58+
/// <returns></returns>
59+
public EntityDynamicFilterBuilder<TEntity> AddFilter<TQueryFilter>() where TQueryFilter : IDynamicQueryFilter<TEntity>
60+
{
61+
return AddFilter(static serviceProvider => serviceProvider.GetRequiredService<TQueryFilter>());
62+
}
63+
64+
#endregion TypeFilter
65+
66+
#region ExpressionFilter
67+
68+
/// <summary>
69+
/// 为实体 <typeparamref name="TEntity"/> 添加基于表达式 <paramref name="predicate"/> 的过滤器
70+
/// </summary>
71+
/// <param name="predicate"></param>
72+
/// <param name="order"></param>
73+
/// <param name="filterPlace"></param>
74+
/// <returns></returns>
75+
public EntityDynamicFilterBuilder<TEntity> AddFilter(Expression<Func<TEntity, bool>> predicate, int order = IDynamicQueryFilter.DefaultOrder, DynamicQueryFilterPlace filterPlace = DynamicQueryFilterPlace.Default)
76+
{
77+
return AddFilter(null!, predicate, order, filterPlace);
78+
}
79+
80+
/// <summary>
81+
/// 为实体 <typeparamref name="TEntity"/> 添加基于表达式 <paramref name="predicate"/> 的过滤器
82+
/// </summary>
83+
/// <param name="name"></param>
84+
/// <param name="predicate"></param>
85+
/// <param name="order"></param>
86+
/// <param name="filterPlace"></param>
87+
/// <returns></returns>
88+
public EntityDynamicFilterBuilder<TEntity> AddFilter(string name, Expression<Func<TEntity, bool>> predicate, int order = IDynamicQueryFilter.DefaultOrder, DynamicQueryFilterPlace filterPlace = DynamicQueryFilterPlace.Default)
89+
{
90+
var queryFilter = new ExpressionDynamicQueryFilter<TEntity>(name, order, filterPlace, predicate);
91+
return AddFilter(_ => queryFilter);
92+
}
93+
94+
/// <summary>
95+
/// 为实体 <typeparamref name="TEntity"/> 添加从 <paramref name="predicateFactory"/> 获取表达式的过滤器
96+
/// </summary>
97+
/// <param name="predicateFactory"></param>
98+
/// <param name="order"></param>
99+
/// <param name="filterPlace"></param>
100+
/// <returns></returns>
101+
public EntityDynamicFilterBuilder<TEntity> AddFilter(Func<IServiceProvider, Expression<Func<TEntity, bool>>> predicateFactory, int order = IDynamicQueryFilter.DefaultOrder, DynamicQueryFilterPlace filterPlace = DynamicQueryFilterPlace.Default)
102+
{
103+
return AddFilter(null!, predicateFactory, order, filterPlace);
104+
}
105+
106+
/// <summary>
107+
/// 为实体 <typeparamref name="TEntity"/> 添加从 <paramref name="predicateFactory"/> 获取表达式的过滤器
108+
/// </summary>
109+
/// <param name="name"></param>
110+
/// <param name="predicateFactory"></param>
111+
/// <param name="order"></param>
112+
/// <param name="filterPlace"></param>
113+
/// <returns></returns>
114+
public EntityDynamicFilterBuilder<TEntity> AddFilter(string name, Func<IServiceProvider, Expression<Func<TEntity, bool>>> predicateFactory, int order = IDynamicQueryFilter.DefaultOrder, DynamicQueryFilterPlace filterPlace = DynamicQueryFilterPlace.Default)
115+
{
116+
return AddFilter(serviceProvider => new ExpressionDynamicQueryFilter<TEntity>(name, order, filterPlace, predicateFactory(serviceProvider)));
117+
}
118+
119+
#endregion ExpressionFilter
120+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
using System.Linq.Expressions;
2+
3+
namespace Microsoft.EntityFrameworkCore.Extensions;
4+
5+
/// <summary>
6+
/// EntityDynamicFilterBuilder 拓展
7+
/// </summary>
8+
public static class EntityDynamicFilterBuilderExtensions
9+
{
10+
#region ExpressionFilter
11+
12+
#region Head
13+
14+
/// <summary>
15+
/// 为实体 <typeparamref name="TEntity"/> 添加基于表达式 <paramref name="predicate"/> 的头部过滤器
16+
/// </summary>
17+
/// <typeparam name="TEntity"></typeparam>
18+
/// <param name="builder"></param>
19+
/// <param name="predicate"></param>
20+
/// <param name="order"></param>
21+
/// <returns></returns>
22+
public static EntityDynamicFilterBuilder<TEntity> AddHeadFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, Expression<Func<TEntity, bool>> predicate, int order = IDynamicQueryFilter.DefaultOrder)
23+
{
24+
return builder.AddFilter(null!, predicate, order, DynamicQueryFilterPlace.Head);
25+
}
26+
27+
/// <summary>
28+
/// 为实体 <typeparamref name="TEntity"/> 添加基于表达式 <paramref name="predicate"/> 的头部过滤器
29+
/// </summary>
30+
/// <typeparam name="TEntity"></typeparam>
31+
/// <param name="builder"></param>
32+
/// <param name="name"></param>
33+
/// <param name="predicate"></param>
34+
/// <param name="order"></param>
35+
/// <returns></returns>
36+
public static EntityDynamicFilterBuilder<TEntity> AddHeadFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, string name, Expression<Func<TEntity, bool>> predicate, int order = IDynamicQueryFilter.DefaultOrder)
37+
{
38+
var queryFilter = new ExpressionDynamicQueryFilter<TEntity>(name, order, DynamicQueryFilterPlace.Head, predicate);
39+
return builder.AddFilter(_ => queryFilter);
40+
}
41+
42+
/// <summary>
43+
/// 为实体 <typeparamref name="TEntity"/> 添加从 <paramref name="predicateFactory"/> 获取表达式的头部过滤器
44+
/// </summary>
45+
/// <typeparam name="TEntity"></typeparam>
46+
/// <param name="builder"></param>
47+
/// <param name="predicateFactory"></param>
48+
/// <param name="order"></param>
49+
/// <returns></returns>
50+
public static EntityDynamicFilterBuilder<TEntity> AddHeadFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, Func<IServiceProvider, Expression<Func<TEntity, bool>>> predicateFactory, int order = IDynamicQueryFilter.DefaultOrder)
51+
{
52+
return builder.AddFilter(null!, predicateFactory, order, DynamicQueryFilterPlace.Head);
53+
}
54+
55+
/// <summary>
56+
/// 为实体 <typeparamref name="TEntity"/> 添加从 <paramref name="predicateFactory"/> 获取表达式的头部过滤器
57+
/// </summary>
58+
/// <typeparam name="TEntity"></typeparam>
59+
/// <param name="builder"></param>
60+
/// <param name="name"></param>
61+
/// <param name="predicateFactory"></param>
62+
/// <param name="order"></param>
63+
/// <returns></returns>
64+
public static EntityDynamicFilterBuilder<TEntity> AddHeadFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, string name, Func<IServiceProvider, Expression<Func<TEntity, bool>>> predicateFactory, int order = IDynamicQueryFilter.DefaultOrder)
65+
{
66+
return builder.AddFilter(serviceProvider => new ExpressionDynamicQueryFilter<TEntity>(name, order, DynamicQueryFilterPlace.Head, predicateFactory(serviceProvider)));
67+
}
68+
69+
#endregion Head
70+
71+
#region Tail
72+
73+
/// <summary>
74+
/// 为实体 <typeparamref name="TEntity"/> 添加基于表达式 <paramref name="predicate"/> 的尾部过滤器
75+
/// </summary>
76+
/// <typeparam name="TEntity"></typeparam>
77+
/// <param name="builder"></param>
78+
/// <param name="predicate"></param>
79+
/// <param name="order"></param>
80+
/// <returns></returns>
81+
public static EntityDynamicFilterBuilder<TEntity> AddTailFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, Expression<Func<TEntity, bool>> predicate, int order = IDynamicQueryFilter.DefaultOrder)
82+
{
83+
return builder.AddFilter(null!, predicate, order, DynamicQueryFilterPlace.Tail);
84+
}
85+
86+
/// <summary>
87+
/// 为实体 <typeparamref name="TEntity"/> 添加基于表达式 <paramref name="predicate"/> 的尾部过滤器
88+
/// </summary>
89+
/// <typeparam name="TEntity"></typeparam>
90+
/// <param name="builder"></param>
91+
/// <param name="name"></param>
92+
/// <param name="predicate"></param>
93+
/// <param name="order"></param>
94+
/// <returns></returns>
95+
public static EntityDynamicFilterBuilder<TEntity> AddTailFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, string name, Expression<Func<TEntity, bool>> predicate, int order = IDynamicQueryFilter.DefaultOrder)
96+
{
97+
var queryFilter = new ExpressionDynamicQueryFilter<TEntity>(name, order, DynamicQueryFilterPlace.Tail, predicate);
98+
return builder.AddFilter(_ => queryFilter);
99+
}
100+
101+
/// <summary>
102+
/// 为实体 <typeparamref name="TEntity"/> 添加从 <paramref name="predicateFactory"/> 获取表达式的尾部过滤器
103+
/// </summary>
104+
/// <typeparam name="TEntity"></typeparam>
105+
/// <param name="builder"></param>
106+
/// <param name="predicateFactory"></param>
107+
/// <param name="order"></param>
108+
/// <returns></returns>
109+
public static EntityDynamicFilterBuilder<TEntity> AddTailFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, Func<IServiceProvider, Expression<Func<TEntity, bool>>> predicateFactory, int order = IDynamicQueryFilter.DefaultOrder)
110+
{
111+
return builder.AddFilter(null!, predicateFactory, order, DynamicQueryFilterPlace.Tail);
112+
}
113+
114+
/// <summary>
115+
/// 为实体 <typeparamref name="TEntity"/> 添加从 <paramref name="predicateFactory"/> 获取表达式的尾部过滤器
116+
/// </summary>
117+
/// <typeparam name="TEntity"></typeparam>
118+
/// <param name="builder"></param>
119+
/// <param name="name"></param>
120+
/// <param name="predicateFactory"></param>
121+
/// <param name="order"></param>
122+
/// <returns></returns>
123+
public static EntityDynamicFilterBuilder<TEntity> AddTailFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, string name, Func<IServiceProvider, Expression<Func<TEntity, bool>>> predicateFactory, int order = IDynamicQueryFilter.DefaultOrder)
124+
{
125+
return builder.AddFilter(serviceProvider => new ExpressionDynamicQueryFilter<TEntity>(name, order, DynamicQueryFilterPlace.Tail, predicateFactory(serviceProvider)));
126+
}
127+
128+
#endregion Tail
129+
130+
#endregion ExpressionFilter
131+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
namespace Microsoft.EntityFrameworkCore.Extensions;
2+
3+
/// <summary>
4+
/// 实体的动态过滤器元数据
5+
/// </summary>
6+
public class EntityDynamicQueryFilterMetadata
7+
{
8+
#region Public 属性
9+
10+
/// <summary>
11+
/// 动态过滤器工厂列表
12+
/// </summary>
13+
public List<Func<IServiceProvider, IDynamicQueryFilter>> DynamicQueryFilterFactories { get; } = [];
14+
15+
/// <summary>
16+
/// 目标类型
17+
/// </summary>
18+
public Type Type { get; set; }
19+
20+
#endregion Public 属性
21+
22+
#region Public 构造函数
23+
24+
/// <inheritdoc cref="EntityDynamicQueryFilterMetadata"/>
25+
public EntityDynamicQueryFilterMetadata(Type type)
26+
{
27+
Type = type ?? throw new ArgumentNullException(nameof(type));
28+
}
29+
30+
#endregion Public 构造函数
31+
}

0 commit comments

Comments
 (0)