您现在的位置: 天下网吧 >> 网吧天地 >> 天下码农 >> 微信小程序 >> 正文

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

2010-12-28vczx佚名

  在日常程序开发、维护、运行过程中,经常出现各种异常,需要多处异常处理程序来捕捉异常,同时进行异常记录,有没有更方便的一种方式呢?最近在看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);

}

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

{
    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;
}

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.最终结果如下图,成功记录了方法调用之前的信息,异常出现的信息,异常处理后返回的值信息,处理之后的其它信息.

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

欢迎访问最专业的网吧论坛,无盘论坛,网吧经营,网咖管理,网吧专业论坛 https://bbs.txwb.com

关注天下网吧微信/下载天下网吧APP/天下网吧小程序,一起来超精彩

本文来源:vczx 作者:佚名

声明
声明:本站所发表的文章、评论及图片仅代表作者本人观点,与本站立场无关。若文章侵犯了您的相关权益,请及时与我们联系,我们会及时处理,感谢您对本站的支持!联系邮箱:support@txwb.com,系统开号,技术支持,服务联系QQ:1175525021本站所有有注明来源为天下网吧或天下网吧论坛的原创作品,各位转载时请注明来源链接!
天下网吧 网吧天下