近日工作中,要实现一个功能,那就是业务层方法里面实现自动缓存。编写业务的c#开发人员只关注如何将业务代码编写正确就可以了,而缓存的代码,大多类似,无非就是判断是否有缓存,有就取出返回,没有就调用数据库代码获取数据再缓存起来而已,于是这部分代码通过使用AOP的方式自动接管掉这种重复性代码。
MrAdvice开源项目github地址:https://github.com/ArxOne/MrAdvice
直接引用MrAdvice.dll文件不能实现AOP拦截功能
因项目原因内外网隔离,且是断网开发的,就只能在外网写个测试程序,然后将MrAdvice。dll文件复制到内网电脑,内网电脑通过引用dll的方式来使用该组件,结果是不会进入到拦截方法的。
通过下图可以看的到,成功解决后,可以实现自动缓存了。
MrAdvice.dll是直接引用的,不是通过nuget安装的,至于这个dll文件的获取,你可以通过nuget获取了找到它即可。
演示程序的源码
控制台入口的代码比较简单,单纯的调用接口。
程序入口代码
程序接口代码
程序接口代码主要是模拟业务方法里面的一些类,定义了一个接口,一个实现类,另外实现类上面是标注了一个自动缓存的特性(AutoCache),该特性的实现代码即为下面所述的核心的AOP拦截代码,具体下面会给出的;另外还有一个输出结果(响应消息)的类,整个源码是放到一个文件里面的,如下所示:
公共接口IJhrscom
{
ResponseResult GetResult (string, DateTime DateTime, int id),
ResponseResult GetPatient (Guid id, ResponseResult t);
}
公共类Jhrscom: IJhrscom
{
[AutoCache (10)]
公共ResponseResult GetPatient (Guid id, ResponseResult t)
{
字符串键=GetKey(新对象[]{id、t});
ResponseResult结果=new ResponseResult(){代码=4444,消息=暗?个方法,
};返回结果;
}
[AutoCache (enableSliding cacheMinutes: 12日:真)]
公共ResponseResult GetResult (string, DateTime DateTime, int id)
{
ResponseResult结果=new ResponseResult(){代码=1122,消息=盎捍娌馐韵?
};字符串键=GetKey(新对象[]{dateTime, id});
返回结果;
}
///& lt; summary>
///缓存关键
///& lt;/summary>
///& lt;参数name=皃ars"祝辞& lt;/param>
///& lt; returns> & lt;/returns>
私人字符串GetKey (params对象[]pars)
{
=new StackFrame var方法(1).GetMethod ();
var=method.GetParameters数组();
var关键=数组。选择(x=比;{[x.Position] .ToJson返回帕尔斯();
}) .ToArray ();var cacheKey=$“{method.DeclaringType.ToString ()} | {method.Name.Replace (“′“,““)} | {string.Join(““,数组。选择(x=比;x.Name)} | {string.Join(““,键)}“.GetMd5 ();
Console.WriteLine ($“【{method.Name.Replace(“′“,““)}】实现类里面的缓存关键:“
+ cacheKey);返回cacheKey;
}
}
///& lt; summary>
///输出结果
///& lt;/summary>
公共类ResponseResult
{
公共int代码{得到;设置;}
公共字符串消息{得到;设置;}
//.....其它属性
}
核心的AOP拦截代码
该代码是用于实现自动缓存功能,思路就是在调用业务方法前,根据缓存钥匙,缓存关键按一定规则生成,保证唯一就可以了,具体源码中有说明,从缓存里面取出数据,如果存在缓存就直接返回给调用者即可,并终止业务方法的执行(体现在不调用context.Proceed()方法上),如果不存在缓存数据或者缓存过期了,则调用业务方法获取数据后并缓存就可以了。