基于微软企业库的AOP组件(含源码)
软件开发,离不开对日志的操作。日志可以帮助我们查找和检测问题,比较传统的日志是在方法执行前或后,手动调用日志代码保存。但自从AOP出现后,我们就可以避免这种繁琐但又必须要实现的方式。本文是在微软企业库的AOP基础上封装出的组件。注意:是使用2.0版本,因为2.0以上版本是基于Net4.5类库的。好了,废话不多说。如图-1所示
图-1
说明
logmethodBillModel文件,是记录AOP详细信息
IBasicCodeService和BasicCodeService是用于测试的接口和实现类
AopUtil是实现Aop的类,核心代码
继续分析代码。
步骤1,先创建2个特性,用于标记在类和方法上,表示这个类中这个方法需要被Aop记录
- /// <summary>
- /// 贴在接口上
- /// </summary>
- public class NSAopHandlerAttribute : HandlerAttribute
- {
- public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
- {
- return new NSAopCallHandler();
- }
- }
- /// <summary>
- /// 贴在方法上,作用:用于开启AOP功能
- /// 开启AOP日志保存
- /// </summary>
- public class NSAopMethodToMethodHandlerAttribute : System.Attribute
- {
- }
步骤2,继承ICallHandler接口实现Aop功能
- public class NSAopCallHandler : ICallHandler
- {
- public int Order { get; set; }
- public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
- {
- //增加其他日志类型,处理方案如下
- //无论是否需记录log_method方法,方法均先执行完成.同时,记录时执行时间
- MethodBase mbCurrent = input.MethodBase;
- string methodName = input.MethodBase.Name;
- string fullName = input.Target.ToString() + "." + methodName;
- //1,方法执行,并记录开始和结束执行时间
- DateTime dtmBegin = DateTime.Now;
- var methodReturn = getNext()(input, getNext);
- DateTime dtmEnd = DateTime.Now;
- TimeSpan ts = dtmEnd - dtmBegin;
- decimal invokeMilliSecond = Convert.ToDecimal(ts.TotalMilliseconds);
- //6,判断是否需保存Aop日志
- object attriToMethod = AttributeHelper.GetCustomAttribute(mbCurrent, "NSAopMethodToMethodHandlerAttribute");
- if (attriToMethod != null )
- {
- string declaringType = input.MethodBase.ToString();
- string instanceName = input.MethodBase.Module.Name;
- //获取参数列表
- Dictionary<string, string> dicParamInfo = new Dictionary<string, string>();
- for (var i = 0; i < input.Arguments.Count; i++)
- {
- string piName = input.Arguments.ParameterName(i);
- string piValue = input.Arguments[i] as string;
- dicParamInfo.Add(piName, piValue);
- }
- //获取方法的层级关系
- //参考地址:http://www.cnblogs.com/mumuliang/p/3939143.html
- string parentFullName = null;
- string parentDeclaringType = null;
- System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace();
- System.Diagnostics.StackFrame[] sfs = st.GetFrames();
- for (int u = 0; u < sfs.Length; ++u)
- {
- System.Reflection.MethodBase mb = sfs[u].GetMethod();
- //数据如下所示
- //[CALL STACK][12]: ExampleAOP.AOPProxy.BasicCodeService.DoSomething1
- //[CALL STACK][13]: ExampleAOP.AOPProxy.AOPProxyTest.Output
- //[CALL STACK][14]: ExampleAOP.Program.Main
- string parentInfo = string.Format("[CALL STACK][{0}]: {1}.{2}", u, mb.DeclaringType.FullName, mb.Name);
- //判断是否包含本方法.若包含,则获取其下一级的数据即可
- string source = mb.Name;
- if (source == methodName)
- {
- if (u + 1 < sfs.Length)
- {
- System.Reflection.MethodBase mbParent = sfs[u + 1].GetMethod();
- parentFullName = mbParent.DeclaringType.FullName + "." + mbParent.Name;
- parentDeclaringType = mbParent.ToString();
- }
- break;
- }
- }
- //记录至全局静态变量
- logmethodBillModel modelLog = new logmethodBillModel()
- {
- MethodName = methodName,
- FullName = fullName,
- DeclaringType = declaringType,
- ParentFullName = parentFullName,
- ParentDeclaringType = parentDeclaringType,
- ParamInfo = dicParamInfo,
- InvokeBeginTime = dtmBegin,
- InvokeEndTime = dtmEnd,
- InvokeMilliSecond = invokeMilliSecond,
- InstanceName = instanceName,
- };
- BaseService.LogMethods.Add(modelLog);
- }
- return methodReturn;
- }
- }
步骤3,就是对接口的使用,当然这里用的是IOC。如下代码所示
- /// <summary>
- /// 创建Service服务类,基于微软企业库
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <returns></returns>
- public static T CreateService<T>() where T : class
- {
- IUnityContainer container = new UnityContainer().AddNewExtension<Interception>();
- container.RegisterType<IBasicCodeService, BasicCodeService>();
- container.Configure<Interception>().SetInterceptorFor<T>(new InterfaceInterceptor());
- T t = container.Resolve<T>();
- return t;
- }
好了,搞定收工。看看调用的代码。so easy
- class Program
- {
- static void Main(string[] args)
- {
- IBasicCodeService baService = BaseService.CreateService<IBasicCodeService>();
- string userName = baService.SingleUserCode("user1");
- List<string> listUserCode = baService.GetListUserCode("code1", "name1");
- System.Console.WriteLine("生成日志个数:" + BaseService.LogMethods.Count);
- System.Console.ReadKey();
- }
- }
这里有一点要说明下,就是接口中有方法1(需记录Aop);方法2(不需记录)。这种情况下,若方法2引用方法1时,也想生成Aop的话,需这样调用,直接使用this是不行的
- public string SingleUserCode(string userCode)
- {
- IBasicCodeService baService = BaseService.CreateService<IBasicCodeService>();
- var listUserCode = baService.GetListUserCode(userCode, "name1");
- return listUserCode[0];
- }
- public List<string> GetListUserCode(string userCode, string userName)
- {
- return new List<string>() { "UserCode1", "UserCode2" };
- }
介绍AOP比较全面的博客
1,关注微信公众号:小特工作室(也可直接扫描签名处二维码)
2,发送:示例4008
即可下载
基于微软企业库的AOP组件(含源码)的更多相关文章
- Prism6下的MEF:基于微软企业库的Cache
通常,应用程序可以将那些频繁访问的数据,以及那些需要大量处理时间来创建的数据存储在内存中,从而提高性能.基于微软的企业库,我们的快速创建一个缓存的实现. 新建PrismSample.Infrastru ...
- 使用Microsoft EnterpriseLibrary(微软企业库)日志组件把系统日志写入数据库和xml文件
这里只是说明在项目中如何配置使用微软企业库的日志组件,对数据库方面的配置请参考其他资料. 1.在项目中添加Microsoft.Practices.EnterpriseLibrary.Data.dll. ...
- 在数据库访问项目中使用微软企业库Enterprise Library,实现多种数据库的支持
在我们开发很多项目中,数据访问都是必不可少的,有的需要访问Oracle.SQLServer.Mysql这些常规的数据库,也有可能访问SQLite.Access,或者一些我们可能不常用的PostgreS ...
- 升讯威ADO.NET增强组件(源码):送给喜欢原生ADO.NET的你
目前我们所接触到的许多项目开发,大多数都应用了 ORM 技术来实现与数据库的交互,ORM 虽然有诸多好处,但是在实际工作中,特别是在大型项目开发中,容易发现 ORM 存在一些缺点,在复杂场景下,反而容 ...
- [EntLib]微软企业库5.0 学习之路——第一步、基本入门
话说在大学的时候帮老师做项目的时候就已经接触过企业库了但是当初一直没明白为什么要用这个,只觉得好麻烦啊,竟然有那么多的乱七八糟的配置(原来我不知道有配置工具可以进行配置,请原谅我的小白). 直到去年在 ...
- 【公开课】《奥威Power-BI基于微软示例库(MSSQL)快速制作管理驾驶舱》文字记录与反馈
本期分享的内容: <奥威Power-BI基于微软示例库(MSSQL)快速制作管理驾驶舱> 时间:2016年11月02日 课程主讲人:叶锡文 从事商业智能行业,有丰富的实施经验,擅长 ...
- 微软企业库的Cache
微软企业库的Cache 通常,应用程序可以将那些频繁访问的数据,以及那些需要大量处理时间来创建的数据存储在内存中,从而提高性能.基于微软的企业库,我们的快速创建一个缓存的实现. 新建PrismSamp ...
- 在开发框架中扩展微软企业库,支持使用ODP.NET(Oracle.ManagedDataAccess.dll)访问Oracle数据库
在前面随笔<在代码生成工具Database2Sharp中使用ODP.NET(Oracle.ManagedDataAccess.dll)访问Oracle数据库,实现免安装Oracle客户端,兼容3 ...
- 10月26日 奥威Power-BI基于微软示例库(MSOLAP)快速制作管理驾驶舱 腾讯课堂开课啦
本次课是基于olap数据源的案例实操课,以微软olap示例库Adventure Works为数据基础. AdventureWorks示例数据库为一家虚拟公司的数据,公司背景为大型跨国生产 ...
随机推荐
- JAVA BASE64
Base64编码说明: Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式. 如果剩下的字符不足3个字节, ...
- java面向对象的三大特性——继承
ul,ol { margin: 0; list-style: none; padding: 0 } a { text-decoration: none; color: inherit } * { ma ...
- java —— equals 与 ==
equals 众所周知,java 中的所有的类都继承自 Object 这个超类 ,他就是Java所有类的父类或祖先类,Object类里面有一个equals方法,并且提供了默认的实现,如下所示. pub ...
- rpm命令的使用
如果服务器配置了本地yum源,大部分的常用软件包都是有的.如果差了头文件或者什么so文件,可以按如下方式找:#以memory.h为例 [root@sz-cdn-centos7-1 tmp]# wher ...
- python并发编程之多进程(理论)
一.什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 二.进程与程序的区别 程序:仅仅是一堆代 进程:是指打开程序运行的过程 三.并发与并行 并发与并行是指cpu运行多个 ...
- mybatis不可忽略的细节
自我总结,欢迎拍砖! 目的:在需要返回int,long等基础类型数据的情况下,尽量在mybatis的Mapper中用基础类型的包装类. 原因:当查询的字段为空值时,mybatis会返回null,用基础 ...
- 理解DNS
理解DNS 写在前面: 目前,我们大部分的网络通信都是基于TCP/IP协议的,而TCP/IP又基于IP地址作为唯一标识进行通信,随着需要记忆的IP地址数量的增多,肯定会超出我们的记忆能力范围,但如果使 ...
- CSS的背景属性和边框属性
CSS的背景属性: background 简写属性,作用是将背景属性设置在一个声明中 background-attachment 背景图像是否固定或者随着页面的其余部分滚动 background-co ...
- JDBC(二)
三层架构的一些基本报结构如下: domain包:下面是一些实体bean,属性为private,提供属性相对应的set和get方法.一般对应于数据库中的一张数据表,属性对应于数据表中的列. dao包,数 ...
- JavaScript中涉及得运算符以及运算符的优先级
在js中主要有三种运算符:算术运算符,逻辑与比较运算符,位运算符.在着三种运算符中,最常见的应该是算术与比较运算符,位运算符比较少见一些 *说到了运算符,就不得不说运算符的优先级.下面我来列一下这些运 ...