Skip to content

Commit

Permalink
优化过滤器配置方式
Browse files Browse the repository at this point in the history
  • Loading branch information
stratosblue committed Dec 31, 2023
1 parent 015632f commit 115dacd
Show file tree
Hide file tree
Showing 9 changed files with 354 additions and 273 deletions.
4 changes: 2 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</PropertyGroup>

<PropertyGroup>
<Version>1.0.0-preview-001</Version>
<Version>1.0.0-preview-002</Version>

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

Expand All @@ -24,7 +24,7 @@
<RepositoryType>git</RepositoryType>
<RepositoryUrl>$(PackageProjectUrl)</RepositoryUrl>

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

<ItemGroup Condition="'$(Configuration)' == 'Release'">
Expand Down
36 changes: 21 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

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

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

### NOTE!!!
Expand Down Expand Up @@ -33,22 +35,26 @@ services.AddDbContext<XXXXContext>((IServiceProvider serviceProvider, DbContextO
```C#
services.AddEntityFrameworkDynamicQueryFilter(options =>
{
//针对实体 User 添加头部表达式过滤器,表达式过滤器根据查询时 ServiceProvider 中的服务状态动态构造,表达式将在查询 User 时拼接到查询头部
options.AddHeadFilter<User>(provider =>
// 配置实体 User 的过滤器
options.Entity<User>(builder =>
{
var currentTenant = provider.GetRequiredService<ICurrentTenant>();
return currentTenant.Id is null
? n => true
: n => n.TenantId == currentTenant.Id;
//添加头部表达式过滤器,表达式过滤器根据查询时 ServiceProvider 中的服务状态动态构造,表达式将在查询 User 时拼接到查询头部
builder.AddHeadFilter(provider =>
{
var currentTenant = provider.GetRequiredService<ICurrentTenant>();
return currentTenant.Id is null
? n => true
: n => n.TenantId == currentTenant.Id;
});

//添加过滤器 MyQueryFilter(从DI容器中获取),其名称、位置、排序由 MyQueryFilter 内部确定
builder.AddFilter<MyQueryFilter>();

//添加尾部表达式过滤器,其名称为 SoftDeletion,表达式将在查询 User 时拼接到查询末尾
builder.AddTailFilter("SoftDeletion", n => n.IsDeleted == false);

//Other options
});

//针对实体 User 添加过滤器 MyQueryFilter(从DI容器中获取),其名称、位置、排序由 MyQueryFilter 内部确定
options.AddFilter<MyQueryFilter, User>();

//添加针对实体 User 的尾部表达式过滤器,其名称为 SoftDeletion,表达式将在查询 User 时拼接到查询末尾
options.AddTailFilter<User>("SoftDeletion", n => n.IsDeleted == false);

//Other options
});
```

Expand Down
120 changes: 120 additions & 0 deletions src/Cuture.EntityFramework.DynamicFilter/EntityDynamicFilterBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using System.Linq.Expressions;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.EntityFrameworkCore.Extensions;

/// <summary>
/// <typeparamref name="TEntity"/> 的动态过滤器构建器
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public class EntityDynamicFilterBuilder<TEntity>
{
#region Private 字段

private readonly EntityDynamicQueryFilterMetadata _metadata;

#endregion Private 字段

#region Public 构造函数

/// <inheritdoc cref="EntityDynamicFilterBuilder{TEntity}"/>
public EntityDynamicFilterBuilder(EntityDynamicQueryFilterMetadata metadata)
{
_metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
}

#endregion Public 构造函数

#region DelegationFilter

internal EntityDynamicFilterBuilder<TEntity> AddFilter(Func<IServiceProvider, IDynamicQueryFilter> queryFilterFactory)
{
_metadata.DynamicQueryFilterFactories.Add(queryFilterFactory);
return this;
}

#endregion DelegationFilter

#region InstanceFilter

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加过滤器 <paramref name="queryFilter"/>
/// </summary>
/// <param name="queryFilter"></param>
/// <returns></returns>
public EntityDynamicFilterBuilder<TEntity> AddFilter(IDynamicQueryFilter<TEntity> queryFilter)
{
return AddFilter(_ => queryFilter);
}

#endregion InstanceFilter

#region TypeFilter

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加过滤器 <typeparamref name="TQueryFilter"/>
/// </summary>
/// <typeparam name="TQueryFilter"></typeparam>
/// <returns></returns>
public EntityDynamicFilterBuilder<TEntity> AddFilter<TQueryFilter>() where TQueryFilter : IDynamicQueryFilter<TEntity>
{
return AddFilter(static serviceProvider => serviceProvider.GetRequiredService<TQueryFilter>());
}

#endregion TypeFilter

#region ExpressionFilter

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加基于表达式 <paramref name="predicate"/> 的过滤器
/// </summary>
/// <param name="predicate"></param>
/// <param name="order"></param>
/// <param name="filterPlace"></param>
/// <returns></returns>
public EntityDynamicFilterBuilder<TEntity> AddFilter(Expression<Func<TEntity, bool>> predicate, int order = IDynamicQueryFilter.DefaultOrder, DynamicQueryFilterPlace filterPlace = DynamicQueryFilterPlace.Default)
{
return AddFilter(null!, predicate, order, filterPlace);
}

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加基于表达式 <paramref name="predicate"/> 的过滤器
/// </summary>
/// <param name="name"></param>
/// <param name="predicate"></param>
/// <param name="order"></param>
/// <param name="filterPlace"></param>
/// <returns></returns>
public EntityDynamicFilterBuilder<TEntity> AddFilter(string name, Expression<Func<TEntity, bool>> predicate, int order = IDynamicQueryFilter.DefaultOrder, DynamicQueryFilterPlace filterPlace = DynamicQueryFilterPlace.Default)
{
var queryFilter = new ExpressionDynamicQueryFilter<TEntity>(name, order, filterPlace, predicate);
return AddFilter(_ => queryFilter);
}

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加从 <paramref name="predicateFactory"/> 获取表达式的过滤器
/// </summary>
/// <param name="predicateFactory"></param>
/// <param name="order"></param>
/// <param name="filterPlace"></param>
/// <returns></returns>
public EntityDynamicFilterBuilder<TEntity> AddFilter(Func<IServiceProvider, Expression<Func<TEntity, bool>>> predicateFactory, int order = IDynamicQueryFilter.DefaultOrder, DynamicQueryFilterPlace filterPlace = DynamicQueryFilterPlace.Default)
{
return AddFilter(null!, predicateFactory, order, filterPlace);
}

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加从 <paramref name="predicateFactory"/> 获取表达式的过滤器
/// </summary>
/// <param name="name"></param>
/// <param name="predicateFactory"></param>
/// <param name="order"></param>
/// <param name="filterPlace"></param>
/// <returns></returns>
public EntityDynamicFilterBuilder<TEntity> AddFilter(string name, Func<IServiceProvider, Expression<Func<TEntity, bool>>> predicateFactory, int order = IDynamicQueryFilter.DefaultOrder, DynamicQueryFilterPlace filterPlace = DynamicQueryFilterPlace.Default)
{
return AddFilter(serviceProvider => new ExpressionDynamicQueryFilter<TEntity>(name, order, filterPlace, predicateFactory(serviceProvider)));
}

#endregion ExpressionFilter
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
using System.Linq.Expressions;

namespace Microsoft.EntityFrameworkCore.Extensions;

/// <summary>
/// EntityDynamicFilterBuilder 拓展
/// </summary>
public static class EntityDynamicFilterBuilderExtensions
{
#region ExpressionFilter

#region Head

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加基于表达式 <paramref name="predicate"/> 的头部过滤器
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="builder"></param>
/// <param name="predicate"></param>
/// <param name="order"></param>
/// <returns></returns>
public static EntityDynamicFilterBuilder<TEntity> AddHeadFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, Expression<Func<TEntity, bool>> predicate, int order = IDynamicQueryFilter.DefaultOrder)
{
return builder.AddFilter(null!, predicate, order, DynamicQueryFilterPlace.Head);
}

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加基于表达式 <paramref name="predicate"/> 的头部过滤器
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="builder"></param>
/// <param name="name"></param>
/// <param name="predicate"></param>
/// <param name="order"></param>
/// <returns></returns>
public static EntityDynamicFilterBuilder<TEntity> AddHeadFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, string name, Expression<Func<TEntity, bool>> predicate, int order = IDynamicQueryFilter.DefaultOrder)
{
var queryFilter = new ExpressionDynamicQueryFilter<TEntity>(name, order, DynamicQueryFilterPlace.Head, predicate);
return builder.AddFilter(_ => queryFilter);
}

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加从 <paramref name="predicateFactory"/> 获取表达式的头部过滤器
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="builder"></param>
/// <param name="predicateFactory"></param>
/// <param name="order"></param>
/// <returns></returns>
public static EntityDynamicFilterBuilder<TEntity> AddHeadFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, Func<IServiceProvider, Expression<Func<TEntity, bool>>> predicateFactory, int order = IDynamicQueryFilter.DefaultOrder)
{
return builder.AddFilter(null!, predicateFactory, order, DynamicQueryFilterPlace.Head);
}

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加从 <paramref name="predicateFactory"/> 获取表达式的头部过滤器
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="builder"></param>
/// <param name="name"></param>
/// <param name="predicateFactory"></param>
/// <param name="order"></param>
/// <returns></returns>
public static EntityDynamicFilterBuilder<TEntity> AddHeadFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, string name, Func<IServiceProvider, Expression<Func<TEntity, bool>>> predicateFactory, int order = IDynamicQueryFilter.DefaultOrder)
{
return builder.AddFilter(serviceProvider => new ExpressionDynamicQueryFilter<TEntity>(name, order, DynamicQueryFilterPlace.Head, predicateFactory(serviceProvider)));
}

#endregion Head

#region Tail

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加基于表达式 <paramref name="predicate"/> 的尾部过滤器
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="builder"></param>
/// <param name="predicate"></param>
/// <param name="order"></param>
/// <returns></returns>
public static EntityDynamicFilterBuilder<TEntity> AddTailFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, Expression<Func<TEntity, bool>> predicate, int order = IDynamicQueryFilter.DefaultOrder)
{
return builder.AddFilter(null!, predicate, order, DynamicQueryFilterPlace.Tail);
}

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加基于表达式 <paramref name="predicate"/> 的尾部过滤器
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="builder"></param>
/// <param name="name"></param>
/// <param name="predicate"></param>
/// <param name="order"></param>
/// <returns></returns>
public static EntityDynamicFilterBuilder<TEntity> AddTailFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, string name, Expression<Func<TEntity, bool>> predicate, int order = IDynamicQueryFilter.DefaultOrder)
{
var queryFilter = new ExpressionDynamicQueryFilter<TEntity>(name, order, DynamicQueryFilterPlace.Tail, predicate);
return builder.AddFilter(_ => queryFilter);
}

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加从 <paramref name="predicateFactory"/> 获取表达式的尾部过滤器
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="builder"></param>
/// <param name="predicateFactory"></param>
/// <param name="order"></param>
/// <returns></returns>
public static EntityDynamicFilterBuilder<TEntity> AddTailFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, Func<IServiceProvider, Expression<Func<TEntity, bool>>> predicateFactory, int order = IDynamicQueryFilter.DefaultOrder)
{
return builder.AddFilter(null!, predicateFactory, order, DynamicQueryFilterPlace.Tail);
}

/// <summary>
/// 为实体 <typeparamref name="TEntity"/> 添加从 <paramref name="predicateFactory"/> 获取表达式的尾部过滤器
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="builder"></param>
/// <param name="name"></param>
/// <param name="predicateFactory"></param>
/// <param name="order"></param>
/// <returns></returns>
public static EntityDynamicFilterBuilder<TEntity> AddTailFilter<TEntity>(this EntityDynamicFilterBuilder<TEntity> builder, string name, Func<IServiceProvider, Expression<Func<TEntity, bool>>> predicateFactory, int order = IDynamicQueryFilter.DefaultOrder)
{
return builder.AddFilter(serviceProvider => new ExpressionDynamicQueryFilter<TEntity>(name, order, DynamicQueryFilterPlace.Tail, predicateFactory(serviceProvider)));
}

#endregion Tail

#endregion ExpressionFilter
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace Microsoft.EntityFrameworkCore.Extensions;

/// <summary>
/// 实体的动态过滤器元数据
/// </summary>
public class EntityDynamicQueryFilterMetadata
{
#region Public 属性

/// <summary>
/// 动态过滤器工厂列表
/// </summary>
public List<Func<IServiceProvider, IDynamicQueryFilter>> DynamicQueryFilterFactories { get; } = [];

/// <summary>
/// 目标类型
/// </summary>
public Type Type { get; set; }

#endregion Public 属性

#region Public 构造函数

/// <inheritdoc cref="EntityDynamicQueryFilterMetadata"/>
public EntityDynamicQueryFilterMetadata(Type type)
{
Type = type ?? throw new ArgumentNullException(nameof(type));
}

#endregion Public 构造函数
}
Loading

0 comments on commit 115dacd

Please sign in to comment.