返回列表 回复 发帖

使用Aop 来处理(记录)应用程序中的异常.

在日常程序开发、维护、运行过程中,经常出现各种异常,需要多处异常处理程序来捕捉异常,同时进行异常记录,有没有更方便的一种方式呢?最近在看Aop的相关实现.应用AOP来处理异常,记录相关信息,同时返回相应的错误值继续程序运行.下面我们来看看异常的相关处理信息.
(一) 首先我们先看一下异常的相关疑点..
      1.异常可以被自动传递,直到处理程序捕捉到为止.这样.
      2.UI层为了良好的用户体验,不能抛出新的异常,替代以更友好的提示信息.
      3.其它地方捕捉异常(UI外)通常处理掉/继续抛出/包装后抛出
      4.如果抛出自定义异常,最好将此异常信息描述的越清晰越好,放边定位,修改程序.
      5.开发试运营阶段,经常出现各种异常问题,或者想掌握相关调用信息,同时处理异常,那么Aop是其中一个解决办法.
(二)Aop处理异常相关应用疑点.
      1.能否捕捉到方法掉用中捕捉到所有异常.
      2.捕捉后记录详细的异常信息,包括异常所在的类、方法、传递InArgs、返回的OutArgs.
      3.记录异常后能否返回相应的返回值.
      4.Aop异常处理所带来的性能问题.
(三)Aop异常处理相关实现.
      1.先定义一个AspectAttribute,此AspectAttribute继承类Attribute,实现接口IContextAttribute,IContextProperty.同时标注 [Serializable,AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)] 保证此类可以序列化,同时可以应用到类和方法上面.有人会说了,既然应用到类上了,那里面的方法不是自动就能调用了,为什么还要定义到方法里面呢,就是可以覆盖类里面的定义
Serializable,AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)]
    public abstract class AspectAttribute:Attribute,IContextAttribute,IContextProperty
    ...{
        public virtual string Name
        ...{
            get
            ...{
                return "Aop";
            }
        }
        public virtual bool IsNewContextOK(Context context)
        ...{
            return true;
        }
        public virtual void Freeze(Context newContext)
        ...{
            return;
        }
        public void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
        ...{
            if (ctorMsg == null)
            ...{
                throw new ArgumentNullException("ctorMsg");
            }
            ctorMsg.ContextProperties.Add(GetContextProperty(Name));
        }
        public virtual bool IsContextOK(Context context, IConstructionCallMessage ctorCallMsg)
        ...{
            if(context == null)
                throw new ArgumentNullException("context");
            if(ctorCallMsg == null)
                throw new ArgumentNullException("ctorCallMsg");
            if(!ctorCallMsg.ActivationType.IsContextful)
                return true;
            object obj = context.GetProperty(Name);
            if((obj != null) && this.Equals(obj))
                return true;
            return false;
        }
        public abstract AspectProperty GetContextProperty(string aopName);
    }

TOP

回复:使用Aop 来处理(记录)应用程序中的异常.

2. 自定义一个上下文属性,以便插入到Aop上下文里面实现接口IContextProperty,IContributeServerContextSink
public virtual IMessageSink GetServerContextSink(IMessageSink nextSink)
  {
   return null;
  } 这里没有任何实现,主要由子类来实现.
3. 自定义一个上下文链AspectSink,来处理异常程序.实现接口IMessageSink.主要的就是这个SyncProcessMessage方法进行Aop 插入处理. public IMessageSink NextSink
        ...{
            get...{ return msgSink;}
        }

        public IMessage SyncProcessMessage(IMessage msg)
        ...{
            IMethodCallMessage callMsg = msg as IMethodCallMessage;
            IMethodReturnMessage returnMsg = this.NextSink.SyncProcessMessage(callMsg) as IMethodReturnMessage;

            if(!(msg is IConstructionCallMessage))
            ...{
                BeforeAopHandle beforeHandle = this.FindBeforeHandle(AopPropertyName);
                if(beforeHandle != null)
                ...{
                    beforeHandle(callMsg);
                }

                AfterAopHandle afterHandle = this.FindAfterHandle(AopPropertyName);
                if(afterHandle != null)
                ...{
                    afterHandle(returnMsg);
                }

                return SyncWrapProcessMessage(msg,returnMsg);
            }
            return returnMsg;
4.这里就是我们异常的自定义ExceptionAttribute,这里主要是关注一下构造函数,看见了没?有个参数object returnValue,这就是代表出现异常时你可以自定义你想要的返回信息.
private object returnValue;

  public ExceptionAttribute()
  ...{}

  public ExceptionAttribute(object returnValue)
  ...{
   this.returnValue = returnValue;
  }



4.这里就是我们异常的自定义ExceptionAttribute,这里主要是关注一下构造函数,看见了没?有个参数object returnValue,这就是代表出现异常时你可以自定义你想要的返回信息.

回复: 使用Aop 来处理(记录)应用程序中的异常.

 5.异常处理链 ExceptionSink.这里实现异常处理,和异常记录功能.主要是对IMethodReturnMessage进行包装,达到处理目的.

public override IMessage SyncWrapProcessMessage(IMessage msg, IMethodReturnMessage returnMsg)
        ...{
            MethodReturnMessageWrapper wrapMsg = new MethodReturnMessageWrapper(returnMsg);
            if(wrapMsg.Exception != null)
            ...{
                wrapMsg.Exception = null;
                object[] logAttribute = returnMsg.MethodBase.GetCustomAttributes(typeof(ExceptionAttribute),true);
                if(logAttribute.Length == 0)
                    logAttribute = returnMsg.MethodBase.DeclaringType.GetCustomAttributes(typeof(ExceptionAttribute),true);
                wrapMsg.ReturnValue = (logAttribute[0] as ExceptionAttribute).ReturnValue;
            }
            return wrapMsg;
        }


(四)Aop异常管理调用测试
1.需要异常管理的类,此处为CalculateTest,它继承ContextBoundObject而来,上有[ExceptionAttribute]约束,代码接受异常管理,默认异常处理后返回null,下面方法public string CalculateLog(int a)则加标签[ExceptionAttribute("I Love You to")]表示,此处覆盖类定义,异常处理后返回的是"I Love You".[ExceptionAttribute(123456789)]异常则返回123456789

[ExceptionAttribute]
    public class CalculateTest : AspectObject
    ...{
        [ExceptionAttribute("I Love You to")]
        public string CalculateLog(int a)
        ...{
            //Thread.Sleep(5000);
            throw new ArgumentOutOfRangeException();
            return Convert.ToString(checked(a*a));
        }

        public object CalculateLog(int a,int b)
        ...{
            //Thread.Sleep(5000);
            throw new ArgumentException();
            return checked(a / b);
        }

        [ExceptionAttribute(123456789)]
        public int CalculateLog(int a,int b,int c)
        ...{
            //Thread.Sleep(5000);
            throw new ArithmeticException();
            return checked(a+b+c);
        }

        public DataSet TestForDataSet(string tableName)
        ...{
            //Thread.Sleep(5000);
            DataSet ds = new DataSet(tableName);
            throw new ConstraintException();
            return ds;
        }
    }


2.测试类

static void Main(string[] args)
        ...{
            CalculateTest cls = new CalculateTest();
            object result0 = cls.CalculateLog(1,2);
            if(result0 != null)
                Console.WriteLine("cls.CalculateLog(1,2)的返回值是:"+result0);
            else
                Console.WriteLine("cls.CalculateLog(1,2)的返回值是:"+"null");
            Console.WriteLine("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

            int result1 = cls.CalculateLog(1,2,3);
            Console.WriteLine("cls.CalculateLog(1,2,3)的返回值是:"+result1);
            Console.WriteLine("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

            string result2 = cls.CalculateLog(1);
            Console.WriteLine("cls.CalculateLog(1)的返回值是:"+result2);
            Console.WriteLine("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

            DataSet ds = cls.TestForDataSet("THIS IS A NULL TABLE");
            if(ds != null)
                Console.WriteLine("cls.TestForDataSet(\"THIS IS A NULL TABLE\")的返回值是:"+ds.DataSetName);
            else
                Console.WriteLine("cls.TestForDataSet(\"THIS IS A NULL TABLE\")的返回值是:"+"null");
            Console.WriteLine("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            Console.ReadLine();

        }


3.最终结果如下图,成功记录了方法调用之前的信息,异常出现的信息,异常处理后返回的值信息,处理之后的其它信息.

使用Aop 来处理(记录)应用程序中的异常. - 〖Asp.Net〗 -  炫浪网络社区 http://ncs.xvna.com/




以上这些就是基础的实现了,还等什么呢 把代码DOWN下去自己编译运行一下, 在类ClassTest加个断点一步一步的调试一下,什么都明白了.以后工作中的异常是不是就可以归Aop处理了呢?
点击此处下载代码: AOP异常处理

返回列表