news 2026/4/23 13:06:22

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/4/23 10:50:19

WordPress插件市场有哪些支持Word公式智能识别的工具?

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

作者头像 李华
网站建设 2026/4/23 12:14:17

大文件上传的原理是什么?如何实现?

2023年X月X日 开发日志 - 大文件传输系统攻坚实录 凌晨1:30&#xff0c;合肥的暴雨敲打着窗户&#xff0c;我正在为这个极具挑战的外包项目设计技术方案。客户的需求相当硬核——基于WebUploader实现20G级文件夹传输&#xff0c;还要兼容IE8这个"上古神器"。泡了杯浓…

作者头像 李华
网站建设 2026/4/23 12:12:15

学长亲荐!专科生必看TOP8AI论文工具测评与推荐

学长亲荐&#xff01;专科生必看TOP8AI论文工具测评与推荐 2026年专科生论文写作工具测评&#xff1a;精准选工具&#xff0c;提升效率 随着AI技术的不断进步&#xff0c;越来越多的学术辅助工具进入高校师生的视野。对于专科生而言&#xff0c;论文写作不仅是学业的重要环节…

作者头像 李华
网站建设 2026/4/21 18:33:53

CORS配置避坑指南,90%开发者忽略的跨域安全细节大公开

第一章&#xff1a;Java解决跨域问题CORS配置 在现代Web开发中&#xff0c;前端与后端分离架构日益普及&#xff0c;跨域资源共享&#xff08;CORS&#xff09;成为必须面对的问题。当浏览器发起的请求目标与当前页面源不同时&#xff0c;会触发同源策略限制&#xff0c;导致请…

作者头像 李华
网站建设 2026/4/18 11:28:43

AI智能获客工具的行业价值和实际应用

我们为何选择AI获客工具来提升业务效能在当今竞争激烈的市场中&#xff0c;我们逐渐发现&#xff0c;传统的客户获取方式已经跟不上企业发展的步伐。AI获客工具&#xff0c;特别是那些强大的智能获客系统&#xff0c;给我们带来了新的突破。这些工具通过数据分析和智能算法&…

作者头像 李华