哈喽,大家好,我是指北君。
故事
最近有个搞C#的新同事加班时抱怨上级给了一个这样无理的需求:
原本代码是这样的:
var code = teamManager.GetCurrentUserCode();
#code 输出: teamA_123
需要达到类似这样的效果:
var newCode = teamManager.GetCurrentUserCode();
#newCode 输出: companyA_teamA_123
注意,这里的teamManager为第三方封装好的接口对象,得不到它的对象源码,无法修改里面的方法。
这位新同事懵懂地如下修改了所有自己调用过“GetCurrentUserCode”的地方:
var companyCode = companyService.GetCurrentCompanyCode();
var newCode = companyCode+"_"+teamManager.GetCurrentUserCode();
//newCode 输出: companyA_teamA_123
看起来很简单,但很繁琐,且不太干净(Clean)。
“哈哈,改完收工!...咦?怎么这个地方还是输出原来的结果?...”
原来还有别处看不见源代码的组件也同样调用了“GetCurrentUserCode”,按需求来说,所有这些地方必须要改。
“但没有源码啊,怎么改?!”他大骂XXX的无理需求。
解决方案
兄弟,别急别急,其实只要不是做得太差的第三方组件,都使用了IOC容器技术,比如Autofac。
现在我们来看看当前较流行的一种优雅解决方法:Autofac + Castle DynamicProxy。
以下示例基于.NET5 版本演示:
1)安装所需要的包:
dotnet add package Autofac.Extras.DynamicProxy
2)引用 Castle.DynamicProxy,定义一个 AddCompanyNameInterceptor 拦截器:
...
using Castle.DynamicProxy;
...
public class AddCompanyNameInterceptor : IInterceptor
{
#我方定义的接口
private readonly ICompanyService companyService;
public AddCompanyNameInterceptor(ICompanyService companyService)
{
this.companyService=companyService;
}
public void Intercept(IInvocation invocation)
{
#原本的对象执行方法
invocation.Proceed();
if(invocation.Method.Name!="GetCurrentUserCode")return;
var oldValueCode=invocation.ReturnValue.ToString();
#oldValueCode 输出: teamA_123
var companyCode = companyService.GetCurrentCompanyCode();
#companyCode 输出: companyA
var newCode=companyCode+"_"+oldValueCode;
#newCode 输出: companyA_teamA_123
#重新设置返回的值
invocation.ReturnValue=newCode;
}
}
3)使用刚刚创建的“AddCompanyNameInterceptor”进行注册拦截:
var autofacBuilder = new ContainerBuilder();
#注册AddCompanyNameInterceptor
autofacBuilder.RegisterType<AddCompanyNameInterceptor>().AsSelf();
#注册拦截 ITeamManager 服务
autofacBuilder.RegisterType<ITeamManager>()
.AsImplementedInterfaces()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(AddCompanyNameInterceptor));
4)之后就可以这样使用:
var teamManager = autofacContainer.Resolve<ITeamManager>();
var newCode = teamManager.GetCurrentUserCode();
#newCode 输出: companyA_teamA_123
聊聊 Castle DynamicProxy
Castle DynamicProxy 作为一个开源的.NET库,其实它背后的思想就是 AOP(Aspect-Oriented Programming,面向切面的编程),意在通过预编译方式和运行期动态代理来实现在不修改源代码的情况下给系统对象动态添加功能的一种技术,属于传统OOP编程的一种补充。AOP广泛地应用日志记录,权限验证,异常拦截等。
当然,以上只是解决方案的一种,其他小伙伴如果有其他方法也可以在评论区留言,帮帮这位新同事。
指北君有话说
关注“开源指北”公众号,我们立志做最好的开源项目分享平台,这里不仅仅有各种有趣且实用的开源项目,还会定期分享关于Java,并发编程,性能优化,中间件服务,架构设计等相关后端知识与面试,就业,找工作,简历模板等就业大计,拥有我就相当于拥有整个互联网宝库,一起来聊一聊吧!
以上就是本次推荐的全部内容啦,这里是指北君,感谢各位的观看。
关注公众号[开源指北]回复[Castle] 即可获取以上项目demo和相关资料,方便你进行测试学习。
相关资料
https://github.com/autofac/Autofac.Extras.DynamicProxy
https://github.com/castleproject
网友评论