zoukankan      html  css  js  c++  java
  • 基于微软企业库的AOP组件(含源码)

    软件开发,离不开对日志的操作。日志可以帮助我们查找和检测问题,比较传统的日志是在方法执行前或后,手动调用日志代码保存。但自从AOP出现后,我们就可以避免这种繁琐但又必须要实现的方式。本文是在微软企业库的AOP基础上封装出的组件。注意:是使用2.0版本,因为2.0以上版本是基于Net4.5类库的。好了,废话不多说。如图-1所示

    1.项目布局.png

    图-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比较全面的博客

    C#进阶系列——AOP?AOP!

     源码下载方式
    1,关注微信公众号:小特工作室(也可直接扫描签名处二维码)
    2,发送:示例4008
    即可下载 
  • 相关阅读:
    在ArcScene中为3D线设置纹理
    沿栅格单元边界生成块状等高线
    利用高程数据找出洼地和内部流域
    ArcMap 无法启动
    在分类渲染时,使用所有唯一值计算直方图
    ArcGIS三维分析扩展模块能否使用3ds max的模型
    如何创建带纹理的Multipatch
    云计算如“工业革命”般袭来 颠覆性改变需过安全关 狼人:
    金山毒霸2012正式公测 首次实现新病毒99秒查杀 狼人:
    瑞星:“云攻击”已成现实 狼人:
  • 原文地址:https://www.cnblogs.com/xiyang1011/p/7794534.html
Copyright © 2011-2022 走看看