1. 过滤器在C#中的核心价值与应用场景
在C#开发中,过滤器(Filter)是一种强大的横切关注点处理机制。它允许我们在不修改核心业务逻辑的情况下,对方法调用或请求处理流程进行拦截和增强。想象一下你正在开发一个电商系统——每个订单处理都需要验证用户权限、记录操作日志、检查输入参数合法性。如果把这些代码直接写在业务方法里,很快就会变成一团乱麻。过滤器正是解决这类问题的银弹。
过滤器模式本质上属于AOP(面向切面编程)的实践,它通过将通用功能从业务代码中剥离出来,实现了关注点分离。在.NET生态中,过滤器主要应用于以下几个典型场景:
- Web请求处理:ASP.NET Core中的Action Filter可以处理请求前后的逻辑,比如权限验证(AuthorizationFilter)、模型验证(ActionFilter)、结果格式化(ResultFilter)等
- 异常处理:通过ExceptionFilter统一捕获和处理异常,避免try-catch块污染业务代码
- 日志记录:用过滤器自动记录方法入参、返回值、执行时间等诊断信息
- 缓存管理:通过过滤器实现缓存读取和更新,比如对GET请求结果进行缓存
- 性能监控:在方法执行前后插入计时逻辑,统计执行耗时
提示:过滤器与中间件(Middleware)的区别在于粒度不同——中间件处理的是HTTP管道级别的逻辑,而过滤器处理的是控制器和Action级别的逻辑。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. ASP.NET Core中的过滤器体系解析
2.1 过滤器管道的工作原理
ASP.NET Core的过滤器管道是一个精密的拦截机制,当请求到达Controller的Action时,会依次经过以下过滤器类型(按执行顺序排列):
- Authorization Filters:最先执行,处理认证和授权(如
[Authorize]) - Resource Filters:在授权之后、模型绑定之前执行,可短路请求(如
IActionFilter) - Action Filters:在Action方法执行前后触发(如
OnActionExecuting和OnActionExecuted) - Exception Filters:捕获Action或Result中抛出的异常
- Result Filters:在Action结果执行前后触发(如
OnResultExecuting和OnResultExecuted)
这个管道机制可以通过一个简单的例子来理解:假设有个获取用户信息的API,请求处理流程就像穿过一系列安检门——先检查证件(Authorization),然后检查行李(Resource),进入操作区(Action),最后打包结果(Result),任何环节发现问题都可以直接返回。
2.2 内置过滤器类型详解
AuthorizationFilter实战
csharp复制public class CustomAuthFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
// 检查请求头中的API密钥
if (!context.HttpContext.Request.Headers.TryGetValue("X-API-KEY", out var apiKey))
{
context.Result = new UnauthorizedResult();
return;
}
// 验证密钥有效性
if (!IsValidApiKey(apiKey))
{
context.Result = new JsonResult(new { error = "Invalid API Key" })
{
StatusCode = StatusCodes.Status403Forbidden
};
}
}
private bool IsValidApiKey(string apiKey) { /* 验证逻辑 */ }
}
ActionFilter的典型应用
csharp复制public class LogActionFilter : IActionFilter
{
private readonly ILogger _logger;
public LogActionFilter(ILogger<LogActionFilter> logger)
{
_logger = logger;
}
public void OnActionExecuting(ActionExecutingContext context)
{
// Action执行前记录入参
_logger.LogInformation($"Executing {context.ActionDescriptor.DisplayName}");
_logger.LogInformation($"Arguments: {JsonSerializer.Serialize(context.ActionArguments)}");
}
public void OnActionExecuted(ActionExecutedContext context)
{
// Action执行后记录结果和耗时
_logger.LogInformation($"Executed {context.ActionDescriptor.DisplayName}");
}
}
3. 自定义过滤器的开发实践
3.1 创建异常处理过滤器
异常处理是Web开发中的常见需求,下面是一个增强版的异常过滤器实现:
csharp复制public class ApiExceptionFilter : IExceptionFilter
{
private readonly IDictionary<Type, Action<ExceptionContext>> _exceptionHandlers;
private readonly IWebHostEnvironment _env;
public ApiExceptionFilter(IWebHostEnvironment env)
{
_env = env;
// 配置特定异常的处理方式
_exceptionHandlers = new Dictionary<Type, Action<ExceptionContext>>
{
{ typeof(ValidationException), HandleValidationException },
{ typeof(NotFoundException), HandleNotFoundException },
{ typeof(UnauthorizedAccessException), HandleUnauthorizedAccessException }
};
}
public void OnException(ExceptionContext context)
{
HandleException(context);
}
private void HandleException(ExceptionContext context)
{
var exceptionType = context.Exception.GetType();
if (_exceptionHandlers.ContainsKey(exceptionType))
{
_exceptionHandlers[exceptionType].Invoke(context);
return;
}
// 默认异常处理
if (!_env.IsDevelopment())
{
context.Result = new JsonResult(new
{
error = "An error occurred while processing your request"
})
{
StatusCode = StatusCodes.Status500InternalServerError
};
context.ExceptionHandled = true;
}
}
private void HandleValidationException(ExceptionContext context)
{
var exception = context.Exception as ValidationException;
context.Result = new BadRequestObjectResult(new
{
error = "Validation failed",
details = exception.Errors
});
context.ExceptionHandled = true;
}
// 其他异常处理方法...
}
3.2 实现性能监控过滤器
性能监控是另一个常见场景,下面这个过滤器可以记录方法执行时间:
csharp复制public class BenchmarkFilter : IActionFilter
{
private Stopwatch _stopwatch;
public void OnActionExecuting(ActionExecutingContext context)
{
_stopwatch = Stopwatch.StartNew();
}
public void OnActionExecuted(ActionExecutedContext context)
{
_stopwatch.Stop();
var actionName = context.ActionDescriptor.DisplayName;
var elapsedMs = _stopwatch.ElapsedMilliseconds;
// 记录到诊断系统
DiagnosticsClient.TrackMetric($"Action_{actionName}_Duration", elapsedMs);
// 添加到响应头
context.HttpContext.Response.Headers.Append("X-Execution-Time", $"{elapsedMs}ms");
}
}
4. 过滤器的高级应用技巧
4.1 过滤器依赖注入的最佳实践
在ASP.NET Core中,过滤器支持依赖注入,但需要注意生命周期管理:
csharp复制// 服务注册时配置过滤器
services.AddScoped<LogActionFilter>();
services.AddControllers(options =>
{
// 全局注册过滤器
options.Filters.Add<LogActionFilter>();
// 或者通过Type方式注册(生命周期由Filter本身控制)
options.Filters.Add(typeof(CustomAuthFilter));
});
// 控制器或Action上使用ServiceFilter特性
[ServiceFilter(typeof(CustomAuthFilter))]
public class SecureController : ControllerBase
{
[ServiceFilter(typeof(BenchmarkFilter))]
public IActionResult Get()
{
return Ok();
}
}
重要提示:避免在过滤器中注入Scoped生命周期的服务作为构造函数参数,除非过滤器本身也是Scoped生命周期。否则可能导致服务实例被不正确地共享。
4.2 过滤器排序与执行控制
当多个过滤器作用于同一个Action时,执行顺序可能影响业务逻辑。ASP.NET Core提供了多种控制方式:
csharp复制// 通过Order属性控制顺序(值越小优先级越高)
[CustomFilter(Order = 1)]
[AnotherFilter(Order = 2)]
public IActionResult Get() { /* ... */ }
// 实现IOrderedFilter接口
public class PriorityFilter : IActionFilter, IOrderedFilter
{
public int Order { get; set; } = 0;
// 实现方法...
}
// 全局过滤器排序
services.AddControllers(options =>
{
options.Filters.Add(new CustomFilter() { Order = 10 });
options.Filters.Add(new AnotherFilter() { Order = 20 });
});
4.3 动态过滤器配置
有时候我们需要根据运行时条件动态启用或配置过滤器:
csharp复制public class DynamicFilterProvider : IFilterProvider
{
private readonly IServiceProvider _serviceProvider;
public DynamicFilterProvider(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public void OnProvidersExecuting(FilterProviderContext context)
{
// 根据条件动态添加过滤器
if (context.ActionContext.HttpContext.Request.Path.StartsWithSegments("/api"))
{
context.Results.Add(new FilterItem(
new FilterDescriptor(new ApiResponseFilter(), FilterScope.Global),
_serviceProvider.GetRequiredService<ApiResponseFilter>()));
}
}
public void OnProvidersExecuted(FilterProviderContext context) { }
}
// 注册自定义FilterProvider
services.AddControllers(options =>
{
options.Filters.Add<DynamicFilterProvider>();
});
5. 过滤器性能优化与疑难解答
5.1 过滤器性能陷阱
虽然过滤器非常强大,但不合理使用会导致性能问题:
-
同步IO操作:在过滤器中执行同步IO(如文件读写、数据库查询)会阻塞请求线程
csharp复制// 错误示例 - 同步读取文件 public void OnActionExecuting(ActionExecutingContext context) { var config = File.ReadAllText("config.json"); // 阻塞调用 // ... } // 正确做法 - 异步读取 public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var config = await File.ReadAllTextAsync("config.json"); // ... await next(); } -
过度复杂的授权逻辑:AuthorizationFilter应尽量简单,复杂的权限检查应考虑缓存策略
-
频繁的对象创建:避免在过滤器中频繁创建大对象,考虑使用对象池或静态资源
5.2 常见问题排查
过滤器不生效的可能原因:
- 生命周期配置错误:过滤器注册为Singleton但依赖了Scoped服务
- 执行顺序冲突:多个过滤器相互覆盖了结果
- 未标记ExceptionHandled:异常过滤器处理后未设置
context.ExceptionHandled = true - DI容器未注册:使用
[ServiceFilter]或[TypeFilter]但未在DI中注册
调试技巧:
- 在过滤器构造函数和方法中添加日志输出
- 使用ASP.NET Core的诊断中间件查看过滤器管道
csharp复制
app.UseEndpoints(endpoints => { endpoints.MapControllers(); endpoints.MapFilterPipeline(); }); - 检查过滤器的Order属性是否导致意外覆盖
6. 实际项目中的过滤器设计模式
6.1 API响应统一包装
在Web API开发中,统一响应格式能显著提升客户端处理效率:
csharp复制public class ApiResponseFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context) { }
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Result is ObjectResult objectResult)
{
context.Result = new JsonResult(new ApiResponse<object>
{
Success = true,
Data = objectResult.Value,
Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
})
{
StatusCode = objectResult.StatusCode
};
}
else if (context.Result is EmptyResult)
{
context.Result = new JsonResult(new ApiResponse
{
Success = true,
Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
});
}
}
}
public class ApiResponse<T>
{
public bool Success { get; set; }
public T Data { get; set; }
public long Timestamp { get; set; }
public string ErrorCode { get; set; }
public string ErrorMessage { get; set; }
}
6.2 多租户请求处理
在SaaS应用中,过滤器可以优雅处理租户隔离:
csharp复制public class TenantResolutionFilter : IActionFilter
{
private readonly ITenantStore _tenantStore;
public TenantResolutionFilter(ITenantStore tenantStore)
{
_tenantStore = tenantStore;
}
public void OnActionExecuting(ActionExecutingContext context)
{
// 从子域名、请求头或JWT中提取租户标识
var tenantId = context.HttpContext.Request.Headers["X-Tenant-Id"].FirstOrDefault()
?? context.HttpContext.User.FindFirst("tenant_id")?.Value;
if (string.IsNullOrEmpty(tenantId))
{
context.Result = new BadRequestObjectResult("Tenant identification required");
return;
}
var tenant = _tenantStore.GetTenant(tenantId);
if (tenant == null)
{
context.Result = new NotFoundObjectResult($"Tenant {tenantId} not found");
return;
}
// 将租户信息存入HttpContext
context.HttpContext.Items["CurrentTenant"] = tenant;
}
public void OnActionExecuted(ActionExecutedContext context) { }
}
6.3 请求限流与防抖
使用ResourceFilter实现API限流:
csharp复制public class RateLimitFilter : IAsyncResourceFilter
{
private readonly IMemoryCache _cache;
private readonly RateLimitOptions _options;
public RateLimitFilter(IMemoryCache cache, IOptions<RateLimitOptions> options)
{
_cache = cache;
_options = options.Value;
}
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
{
var clientIp = context.HttpContext.Connection.RemoteIpAddress?.ToString();
if (string.IsNullOrEmpty(clientIp))
{
await next();
return;
}
var cacheKey = $"rate_limit_{clientIp}";
var requestCount = _cache.GetOrCreate(cacheKey, entry =>
{
entry.AbsoluteExpirationRelativeToNow = _options.Window;
return 0;
});
if (requestCount >= _options.MaxRequests)
{
context.Result = new ContentResult
{
Content = "Too many requests",
StatusCode = StatusCodes.Status429TooManyRequests
};
return;
}
_cache.Set(cacheKey, requestCount + 1);
await next();
}
}
public class RateLimitOptions
{
public TimeSpan Window { get; set; } = TimeSpan.FromMinutes(1);
public int MaxRequests { get; set; } = 100;
}
7. 过滤器与其他.NET技术的整合
7.1 与MediatR的协同工作
在CQRS架构中,过滤器可以与MediatR完美配合:
csharp复制public class MediatRLoggingFilter<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly ILogger<MediatRLoggingFilter<TRequest, TResponse>> _logger;
public MediatRLoggingFilter(ILogger<MediatRLoggingFilter<TRequest, TResponse>> logger)
{
_logger = logger;
}
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
_logger.LogInformation($"Handling {typeof(TRequest).Name}");
try
{
var response = await next();
_logger.LogInformation($"Handled {typeof(TRequest).Name}");
return response;
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error handling {typeof(TRequest).Name}");
throw;
}
}
}
// 注册MediatR管道行为
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(MediatRLoggingFilter<,>));
7.2 与Health Checks的集成
利用过滤器增强健康检查端点:
csharp复制public class HealthCheckFilter : IActionFilter
{
private readonly HealthCheckService _healthCheck;
public HealthCheckFilter(HealthCheckService healthCheck)
{
_healthCheck = healthCheck;
}
public void OnActionExecuting(ActionExecutingContext context)
{
if (context.ActionDescriptor.DisplayName.Contains("Health"))
{
// 为健康检查端点添加特殊请求头
context.HttpContext.Response.Headers.Append("Cache-Control", "no-store, max-age=0");
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Result is HealthCheckResult healthResult)
{
// 对健康检查结果进行后处理
if (healthResult.Status == HealthStatus.Unhealthy)
{
context.HttpContext.Response.Headers.Append("X-Health-Critical", "true");
}
}
}
}
7.3 与gRPC服务的结合
gRPC拦截器本质上也是一种过滤器模式:
csharp复制public class GrpcLoggingInterceptor : Interceptor
{
private readonly ILogger<GrpcLoggingInterceptor> _logger;
public GrpcLoggingInterceptor(ILogger<GrpcLoggingInterceptor> logger)
{
_logger = logger;
}
public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
TRequest request,
ServerCallContext context,
UnaryServerMethod<TRequest, TResponse> continuation)
{
_logger.LogInformation($"Starting gRPC call: {context.Method}");
try
{
return await continuation(request, context);
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error in gRPC call: {context.Method}");
throw;
}
}
}
// 注册gRPC拦截器
services.AddGrpc(options =>
{
options.Interceptors.Add<GrpcLoggingInterceptor>();
});
8. 测试驱动下的过滤器开发
8.1 单元测试过滤器逻辑
过滤器作为独立组件应该被充分测试:
csharp复制public class AuthorizationFilterTests
{
[Fact]
public void OnAuthorization_WithValidApiKey_ShouldPass()
{
// 准备
var filter = new CustomAuthFilter();
var context = new AuthorizationFilterContext(
new ActionContext(
new DefaultHttpContext(),
new RouteData(),
new ActionDescriptor()),
new List<IFilterMetadata>());
context.HttpContext.Request.Headers["X-API-KEY"] = "valid-key";
// 执行
filter.OnAuthorization(context);
// 断言
Assert.Null(context.Result);
}
[Fact]
public void OnAuthorization_WithoutApiKey_ShouldReturn401()
{
// 准备
var filter = new CustomAuthFilter();
var context = new AuthorizationFilterContext(
new ActionContext(
new DefaultHttpContext(),
new RouteData(),
new ActionDescriptor()),
new List<IFilterMetadata>());
// 执行
filter.OnAuthorization(context);
// 断言
Assert.IsType<UnauthorizedResult>(context.Result);
}
}
8.2 集成测试过滤器管道
测试过滤器在完整管道中的行为:
csharp复制public class FilterIntegrationTests : IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _factory;
public FilterIntegrationTests(WebApplicationFactory<Startup> factory)
{
_factory = factory.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.AddControllers(options =>
{
options.Filters.Add<CustomAuthFilter>();
});
});
});
}
[Fact]
public async Task Get_WithValidApiKey_ShouldReturn200()
{
// 准备
var client = _factory.CreateClient();
client.DefaultRequestHeaders.Add("X-API-KEY", "valid-key");
// 执行
var response = await client.GetAsync("/api/protected");
// 断言
response.EnsureSuccessStatusCode();
}
}
8.3 模拟依赖的测试策略
当过滤器依赖外部服务时,使用Mock对象进行测试:
csharp复制public class TenantFilterTests
{
[Fact]
public void OnActionExecuting_WithInvalidTenant_ShouldReturn404()
{
// 准备Mock
var tenantStoreMock = new Mock<ITenantStore>();
tenantStoreMock.Setup(x => x.GetTenant("invalid"))
.Returns((Tenant)null);
var filter = new TenantResolutionFilter(tenantStoreMock.Object);
var context = new ActionExecutingContext(
new ActionContext(
new DefaultHttpContext(),
new RouteData(),
new ActionDescriptor()),
new List<IFilterMetadata>(),
new Dictionary<string, object>(),
null);
context.HttpContext.Request.Headers["X-Tenant-Id"] = "invalid";
// 执行
filter.OnActionExecuting(context);
// 断言
Assert.IsType<NotFoundObjectResult>(context.Result);
}
}
9. 性能关键型场景的过滤器优化
9.1 缓存响应过滤器
对于高并发读场景,实现响应缓存:
csharp复制public class CacheResponseFilter : IActionFilter
{
private readonly IMemoryCache _cache;
private readonly ILogger _logger;
public CacheResponseFilter(IMemoryCache cache, ILogger<CacheResponseFilter> logger)
{
_cache = cache;
_logger = logger;
}
public void OnActionExecuting(ActionExecutingContext context)
{
if (context.HttpContext.Request.Method != "GET") return;
var cacheKey = GenerateCacheKey(context);
if (_cache.TryGetValue(cacheKey, out object cachedResult))
{
_logger.LogDebug($"Cache hit for {cacheKey}");
context.Result = new ObjectResult(cachedResult);
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.HttpContext.Request.Method != "GET") return;
if (context.Result is not ObjectResult objectResult) return;
var cacheKey = GenerateCacheKey(context);
_cache.Set(cacheKey, objectResult.Value, TimeSpan.FromMinutes(5));
_logger.LogDebug($"Cache set for {cacheKey}");
}
private string GenerateCacheKey(FilterContext context)
{
var path = context.HttpContext.Request.Path;
var query = context.HttpContext.Request.QueryString;
return $"response_cache_{path}{query}";
}
}
9.2 异步流处理过滤器
处理大文件上传或下载时,使用异步流避免内存爆炸:
csharp复制public class StreamProcessingFilter : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// 处理上传流
foreach (var argument in context.ActionArguments.Values.OfType<IFormFile>())
{
if (argument.Length > 0)
{
using var memoryStream = new MemoryStream();
await argument.CopyToAsync(memoryStream);
// 处理文件内容...
}
}
var executedContext = await next();
// 处理下载流
if (executedContext.Result is FileStreamResult fileResult)
{
executedContext.HttpContext.Response.Headers.Append("X-Streamed", "true");
}
}
}
9.3 最小化过滤器开销
对于性能敏感场景,优化过滤器实现:
csharp复制// 高性能日志过滤器
public class HighPerfLogFilter : IActionFilter
{
private static readonly ConcurrentDictionary<string, Action<ILogger, string, Exception>> _logActions = new();
public void OnActionExecuting(ActionExecutingContext context)
{
if (!Logger.IsEnabled(LogLevel.Information)) return;
var actionName = context.ActionDescriptor.DisplayName;
var logAction = _logActions.GetOrAdd(actionName, name =>
LoggerMessage.Define<string>(LogLevel.Information,
new EventId(1, "ActionExecuting"),
$"Executing {name}"));
logAction(_logger, null, null);
}
// 其他方法...
}
10. 前沿技术与过滤器的未来演进
10.1 源生成器优化过滤器性能
C# 9.0引入的源生成器可以优化过滤器性能:
csharp复制[Generator]
public class FilterSourceGenerator : ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
context.RegisterForSyntaxNotifications(() => new FilterSyntaxReceiver());
}
public void Execute(GeneratorExecutionContext context)
{
if (context.SyntaxContextReceiver is not FilterSyntaxReceiver receiver)
return;
foreach (var filterClass in receiver.FilterClasses)
{
var source = GenerateFilterProxy(filterClass);
context.AddSource($"{filterClass.Name}_proxy.cs", source);
}
}
private string GenerateFilterProxy(INamedTypeSymbol filterClass)
{
// 生成高性能代理类代码...
}
}
// 自动生成的高性能过滤器
[GeneratedFilter]
public partial class AutoLogFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
=> GeneratedOnActionExecuting(context);
public void OnActionExecuted(ActionExecutedContext context)
=> GeneratedOnActionExecuted(context);
}
10.2 基于编译时分析的过滤器验证
使用Roslyn分析器确保过滤器正确实现:
csharp复制[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class FilterAnalyzer : DiagnosticAnalyzer
{
public const string MissingOrderId = "FILTER001";
private static readonly DiagnosticDescriptor MissingOrderRule = new(
MissingOrderId,
"Filters should implement IOrderedFilter",
"Filter '{0}' should implement IOrderedFilter to avoid execution order issues",
"Design",
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
=> ImmutableArray.Create(MissingOrderRule);
public override void Initialize(AnalysisContext context)
{
context.RegisterSymbolAction(AnalyzeFilter, SymbolKind.NamedType);
}
private void AnalyzeFilter(SymbolAnalysisContext context)
{
var namedType = (INamedTypeSymbol)context.Symbol;
if (!IsFilterType(namedType)) return;
if (!namedType.AllInterfaces.Any(x => x.Name == nameof(IOrderedFilter)))
{
var diagnostic = Diagnostic.Create(
MissingOrderRule,
namedType.Locations[0],
namedType.Name);
context.ReportDiagnostic(diagnostic);
}
}
private bool IsFilterType(INamedTypeSymbol type)
{
return type.AllInterfaces.Any(x =>
x.Name.StartsWith("I") && x.Name.EndsWith("Filter"));
}
}
10.3 机器学习驱动的动态过滤器
结合ML.NET实现智能过滤器:
csharp复制public class SmartThrottlingFilter : IAsyncActionFilter
{
private readonly PredictionEngine<RequestFeatures, ThrottlingPrediction> _predictionEngine;
public SmartThrottlingFilter(ITransformer mlModel)
{
_predictionEngine = mlModel.CreatePredictionEngine<RequestFeatures, ThrottlingPrediction>();
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var features = ExtractFeatures(context);
var prediction = _predictionEngine.Predict(features);
if (prediction.ShouldThrottle)
{
context.Result = new ObjectResult("Too many requests")
{
StatusCode = StatusCodes.Status429TooManyRequests
};
return;
}
await next();
}
private RequestFeatures ExtractFeatures(ActionExecutingContext context)
{
// 从请求中提取特征...
}
}
public class RequestFeatures
{
[LoadColumn(0)] public string ClientIP { get; set; }
[LoadColumn(1)] public string UserAgent { get; set; }
[LoadColumn(2)] public float RequestsPerMinute { get; set; }
// 其他特征...
}
public class ThrottlingPrediction
{
[ColumnName("PredictedLabel")]
public bool ShouldThrottle { get; set; }
public float Probability { get; set; }
}
