news 2026/5/7 13:23:56

C#进阶疗法 -- 拦截器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C#进阶疗法 -- 拦截器

代码拦截器入门指南:使用 Castle.DynamicProxy 实现方法拦截

什么是代码拦截器?

代码拦截器是一种设计模式,允许我们在不修改原有代码的情况下,在方法执行前后插入自定义逻辑。这种技术在很多场景下非常有用,属于aop编程的范畴,比如:

  • 日志记录
  • 性能监控
  • 事务管理
  • 权限验证
  • 异常处理

为什么需要代码拦截器?

在传统的代码编写中,如果我们需要为多个方法添加相同的逻辑(比如日志记录),通常需要在每个方法中重复编写这些代码,这会导致代码冗余和维护困难。使用代码拦截器,我们可以将这些通用逻辑集中到一个地方,然后应用到多个方法上,从而减少代码冗余,提高代码的可维护性。

如何使用 Castle.DynamicProxy 实现代码拦截器?

Castle.DynamicProxy 是一个强大的库,允许我们在运行时创建代理对象,从而实现方法拦截。下面我们将通过一个具体的示例来演示如何使用 Castle.DynamicProxy 实现代码拦截器。

步骤 1:安装 Castle.DynamicProxy 包

首先,我们需要在项目中安装 Castle.DynamicProxy 包。可以通过 NuGet 包管理器或者命令行来安装:

dotnet add package Castle.Core

步骤 2:创建拦截器类

接下来,我们需要创建一个拦截器类,实现IInterceptor接口:

usingCastle.DynamicProxy;namespaceFrameLearning.BasicComponents{/// <summary>/// 拦截器/// </summary>publicclassLogInterceptor:IInterceptor{publicvoidIntercept(IInvocationinvocation){Console.WriteLine($"开始调用:{invocation.Method.Name}");// 执行原方法invocation.Proceed();Console.WriteLine($"结束调用:{invocation.Method.Name},返回值:{invocation.ReturnValue}");}}}

在这个示例中,我们创建了一个LogInterceptor类,它实现了IInterceptor接口的Intercept方法。在Intercept方法中,我们首先打印出方法名,表示方法开始调用,然后调用invocation.Proceed()执行原方法,最后打印出方法名和返回值,表示方法结束调用。

步骤 3:注册拦截器和目标服务

在 Program.cs 文件中,我们需要注册拦截器和目标服务:

// 注册 Castle.DynamicProxy.ProxyGenerator 服务builder.Services.AddSingleton<Castle.DynamicProxy.ProxyGenerator,Castle.DynamicProxy.ProxyGenerator>();// 注册拦截器builder.Services.AddScoped<LogInterceptor>();// 注册目标服务(使用代理)builder.Services.AddScoped<IUserServer>(provider=>{// 从 DI 容器获取代理生成器varproxyGenerator=provider.GetRequiredService<ProxyGenerator>();// 从 DI 容器获取拦截器varinterceptor=provider.GetRequiredService<LogInterceptor>();// 创建目标服务实例vartarget=newUserServer();// 生成代理对象并返回returnproxyGenerator.CreateInterfaceProxyWithTarget<IUserServer>(target,interceptor);});

在这个示例中,我们首先注册了Castle.DynamicProxy.ProxyGenerator服务,然后注册了LogInterceptor拦截器,最后注册了IUserServer服务,但是我们返回的不是UserServer的直接实例,而是通过proxyGenerator.CreateInterfaceProxyWithTarget方法创建的代理对象,这个代理对象会应用我们的LogInterceptor拦截器。

步骤 4:创建目标服务接口和实现

我们需要创建目标服务接口和实现,以便拦截器可以拦截其方法调用:

// IUserServer.csnamespaceFrameLearning.Servers{publicinterfaceIUserServer{publicList<string>GetRoles();}}// UserServer.csnamespaceFrameLearning.Servers{publicclassUserServer:IUserServer{publicList<string>GetRoles(){List<string>roles=newList<string>();roles.Add("Admin");returnroles;}}}

在这个示例中,我们创建了一个IUserServer接口,它有一个GetRoles方法,然后创建了一个UserServer类,实现了这个接口。

步骤 5:使用拦截器

现在,我们可以在控制器中使用IUserServer服务,拦截器会自动拦截其方法调用:

[HttpPost("login")][AllowAnonymous]publicIActionResultLogin([FromBody]UserCredentialscredentials){varroles=_userServer.GetRoles();// 生成tokenvartoken=_jwtService.GenerateToken(credentials.Username,roles);returnOk(newUserResponse{Username=credentials.Username,Token=token,Roles=roles});}

在这个示例中,当我们调用_userServer.GetRoles()方法时,LogInterceptor会自动拦截这个调用,在方法执行前后打印日志。

代码拦截器的应用场景

代码拦截器在很多场景下都非常有用,下面列举几个常见的应用场景:

1. 日志记录

如我们在示例中所示,我们可以使用拦截器在方法执行前后记录日志,这样可以方便我们了解方法的执行情况,而不需要在每个方法中手动添加日志代码。

2. 性能监控

我们可以使用拦截器来监控方法的执行时间,从而了解哪些方法执行较慢,需要优化:

publicclassPerformanceInterceptor:IInterceptor{privatereadonlyILogger<PerformanceInterceptor>_logger;publicPerformanceInterceptor(ILogger<PerformanceInterceptor>logger){_logger=logger;}publicvoidIntercept(IInvocationinvocation){varstopwatch=Stopwatch.StartNew();try{invocation.Proceed();}finally{stopwatch.Stop();_logger.LogInformation($"方法{invocation.Method.Name}执行时间:{stopwatch.ElapsedMilliseconds}ms");}}}

3. 事务管理

我们可以使用拦截器来管理事务,确保方法执行过程中的所有操作都在一个事务中:

publicclassTransactionInterceptor:IInterceptor{privatereadonlyIDbContext_dbContext;publicTransactionInterceptor(IDbContextdbContext){_dbContext=dbContext;}publicvoidIntercept(IInvocationinvocation){usingvartransaction=_dbContext.Database.BeginTransaction();try{invocation.Proceed();transaction.Commit();}catch(Exception){transaction.Rollback();throw;}}}

4. 权限验证

我们可以使用拦截器来验证用户是否有权限执行某个方法:

publicclassAuthorizationInterceptor:IInterceptor{privatereadonlyIHttpContextAccessor_httpContextAccessor;publicAuthorizationInterceptor(IHttpContextAccessorhttpContextAccessor){_httpContextAccessor=httpContextAccessor;}publicvoidIntercept(IInvocationinvocation){varuser=_httpContextAccessor.HttpContext.User;if(!user.Identity.IsAuthenticated){thrownewUnauthorizedAccessException("用户未登录");}varrequiredRoles=invocation.Method.GetCustomAttributes<AuthorizeAttribute>().SelectMany(attr=>attr.Roles.Split(',')).ToList();if(requiredRoles.Any()&&!requiredRoles.Any(role=>user.IsInRole(role))){thrownewForbiddenAccessException("用户没有权限执行此操作");}invocation.Proceed();}}

总结

代码拦截器是一种强大的技术,允许我们在不修改原有代码的情况下,在方法执行前后插入自定义逻辑。使用 Castle.DynamicProxy,我们可以轻松实现代码拦截器,从而提高代码的可维护性和可扩展性。

在实际应用中,我们可以根据具体的需求,创建不同类型的拦截器,比如日志拦截器、性能监控拦截器、事务管理拦截器、权限验证拦截器等,从而实现各种横切关注点的分离。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/6 6:38:06

C#进阶疗法 -- 过滤器

ASP.NET Core 代码过滤器入门指南&#xff1a;实现统一处理 什么是代码过滤器&#xff1f; 代码过滤器是 ASP.NET Core 中的一种组件&#xff0c;允许我们在请求处理管道的不同阶段执行自定义逻辑。它们提供了一种声明式的方式来处理横切关注点&#xff08;cross-cutting conce…

作者头像 李华
网站建设 2026/5/3 9:50:24

2026必备!专科生论文痛点TOP10 AI论文网站测评

2026必备&#xff01;专科生论文痛点TOP10 AI论文网站测评 2026年专科生论文写作工具深度测评 随着人工智能技术的不断进步&#xff0c;AI论文辅助工具已成为众多专科生提升写作效率、优化内容质量的重要帮手。然而&#xff0c;面对市场上琳琅满目的平台&#xff0c;如何选择…

作者头像 李华
网站建设 2026/5/7 2:58:36

【Web自动化进阶指南】:掌握Selenium模拟登录与元素精准点击

第一章&#xff1a;Web自动化进阶的核心价值 在现代软件开发与测试体系中&#xff0c;Web自动化已从基础的脚本录制迈向智能化、可维护性强的高级阶段。进阶的Web自动化不仅提升测试效率&#xff0c;更在持续集成/持续交付&#xff08;CI/CD&#xff09;流程中扮演关键角色&…

作者头像 李华
网站建设 2026/5/7 10:52:18

Face Fusion清空按钮失效?常见操作异常处理解决方案

Face Fusion清空按钮失效&#xff1f;常见操作异常处理解决方案 1. 问题背景与使用场景 你是不是也遇到过这种情况&#xff1a;在使用 Face Fusion WebUI 进行人脸融合时&#xff0c;点击「清空」按钮毫无反应&#xff0c;上传的图片、参数设置、结果预览全都卡在那里动不了&…

作者头像 李华
网站建设 2026/5/2 21:33:07

Vue.js vs React:全面对比

核心哲学差异方面Vue.jsReact设计理念渐进式框架声明式UI库核心思想"关爱开发者""拥抱函数式编程"学习曲线平缓&#xff0c;渐进式陡峭&#xff0c;概念较多模板 vs JSX模板为主JSX 为主1. 架构设计差异Vue - 渐进式框架<!-- Vue 2/3 模板语法 --> &…

作者头像 李华
网站建设 2026/5/1 8:29:00

网页编辑器如何优化WordPress的PPT公式远程协作功能?

要求&#xff1a;开源&#xff0c;免费&#xff0c;技术支持 博客&#xff1a;WordPress 开发语言&#xff1a;PHP 数据库&#xff1a;MySQL 功能&#xff1a;导入Word,导入Excel,导入PPT(PowerPoint),导入PDF,复制粘贴word,导入微信公众号内容,web截屏 平台&#xff1a;Window…

作者头像 李华