当前位置: 首页 > news >正文

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,我们可以轻松实现代码拦截器,从而提高代码的可维护性和可扩展性。

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

http://www.jsqmd.com/news/278622/

相关文章:

  • 浙江正规的胶辊包胶供应商有哪些,泰兴金茂辊业特色显著
  • Spring Cloud Gateway鉴权过滤器深度剖析(架构师私藏笔记曝光)
  • 国产化替代中WordPress如何兼容信创环境公式编辑?
  • 收藏!大模型转型实战指南:从入门到求职,避坑全攻略
  • 从Python到GPU加速:构建深度学习环境的6条黄金指令
  • 2025光纤滑环排行:国内热门款性能大PK,滑环定制/气动旋转接头/滑环/定制滑环/旋转接头,光纤滑环企业怎么选
  • 探讨膨胀管品牌商,南京哪家值得推荐,价格如何
  • 前端开发者如何在WordPress中实现Excel公式动态绑定?
  • 2026年消防水带厂家推荐:基于多场景实测评价,针对渗漏与霉腐痛点精准指南
  • 为什么90%的人都写不对提取链接的正则?专家级避坑指南来了
  • Java解决跨域问题完整指南(CORS配置从入门到生产级落地)
  • 5.3 规模化管理:基于目录 vs 基于分支的多环境 多集群治理策略
  • Vue.js vs React:全面对比
  • 仅需4步!快速将Python程序打包成小巧稳定的exe应用(附完整实例)
  • 2026年膨胀管厂家推荐,这几家在北上广口碑都不错
  • 【Maven依赖冲突排查与解决】:20年架构师亲授5大核心技巧,快速定位并解决依赖难题
  • 【Java集合类深度解析】:HashMap底层实现原理揭秘与性能优化策略
  • 推荐靠谱的隔膜气压罐供应商,柏甲控制专业有保障
  • 5.4 避坑指南:GitOps 生产环境常见故障排查与性能调优
  • 线性注意力(Linear Attention, LA)学习
  • Maven依赖冲突终极解决方案(资深专家实战经验总结)
  • BthAvrcpAppSvc.dll文件丢失找不到 免费下载方法分享
  • 分享广州靠谱的隔膜气压罐供应商,推荐哪家?
  • 网页编辑器如何优化WordPress的PPT公式远程协作功能?
  • 6.1 拒绝裸奔:DevSecOps 核心理念与全链路安全架构设计
  • 2026年分析太原外贸网站建设老牌定制公司,哪家排名靠前?
  • AF488标记的Streptavidin,AF488-链霉亲和素:一种基于生物素系统的荧光检测工具
  • WordPress插件市场有哪些支持Word公式智能识别的工具?
  • MyBatis-Plus遇上Spring Boot 3后究竟发生了什么?(深度解析底层集成原理)
  • Face Fusion清空按钮失效?常见操作异常处理解决方案