木野狐(Neil Chen)

Speak less, do more.

这两天写 ASP.NET 写晕了,老想偷点懒。由于在后台的代码里几乎每个方法里都要 try..catch 这么来一遍,感觉很烦琐。又联想到 AOP, 但 AOP 的做法相对比较复杂,做法也很多。比如用 Dynamic Proxy, Attribute, 或者 Emit 等。我忽然联想到了 C# 2.0 的新特性匿名委托,觉得这个虽然丑一点。。。不过其实也可以比较轻量级的简单模拟 AOP 的效果:

// asp.net 里面强制做一个页面基类的要求是不过分的。。。
public partial class TestLogger: PageBase {
    
protected void Page_Load(object sender, EventArgs e) {
        
// 这个方法实现在页面基类里面,可以往里面实现通用的异常处理,日志逻辑等。
        TryDo(
            
// 这个里面干实际的事情
            delegate() {
                
int a = 1;
                
int b = 0;
                
int c = a / b;
            },
            
// 这是一个可选的异常处理,如果传递一个 null 就会干脆忽略异常
            delegate() {
                Response.Write(
"Sorry, 发生了一个错误。");
            }
        );
    }
}

在页面基类里面的实现代码就很简单了,也可以方便的统一管理。这里我假定仅仅简单的用 log4net 来对异常做日志记录:
using System;
using System.Web.UI;
using log4net;

namespace SomeNamespace {
    
// 定义一个简单的委托用于传递匿名委托
    public delegate void MyAction();
    
    
// 定义页面基类
    public class PageBase : Page {
        
protected ILog logger;

        
// 页面基类里面集中处理所有异常处理逻辑
        protected void TryDo(MyAction doHandler, MyAction exceptHandler) {
            
try {
                
// 干点儿实际的事情
                doHandler();
            } 
catch (Exception ex) { 
                
// 简单的记录异常
                logger.Error(ex);
                
                
// 其他一些处理
                
// 。。。

                
// 调用自定义的异常处理,这里没有回传 Exception 的具体信息。因为反正没有必要对用户显示了。。。
                if (exceptHandler != null)
                    exceptHandler();
            }
        }

        
protected override void OnInit(EventArgs e) {
            
// 初始化 logger. 正好这里 GetType() 可以取到子类的实际类型
            logger = LogManager.GetLogger(this.GetType());

            
base.OnInit(e);
        }
    }
}
 
好了,先写到这里。这只是我的一个简单想法。目的在轻量级的实现异常或日志的集中管理。当然这个和完整的 AOP 概念是没法比的,不过话说回来,好像目前在 .NET 中还没有很完美的 AOP framework.
posted on 2006-11-16 02:46 木野狐(Neil Chen) 阅读(2387) 评论(10)  编辑 收藏 所属分类: .NET 综合

Feedback

#1楼  2006-11-16 02:50 FantasySoft      
我觉得我应该是第一个读者吧,呵呵~~
  回复  引用  查看    

#2楼 [楼主] 2006-11-16 02:53 木野狐      
哈哈,我晕。你也没睡啊。

  回复  引用  查看    

#3楼  2006-11-16 08:51 壮志      
好象也没有简化多少
  回复  引用  查看    

#4楼 [楼主] 2006-11-16 10:19 木野狐      
@壮志
这个的主要作用不是语法上的简化,而是异常处理策略的统一。
  回复  引用  查看    

呵呵..受到啟發了
  回复  引用    

#6楼  2006-11-16 18:38 杨锦添 [未注册用户]
不错,,有点意思!!!!!!
  回复  引用    

#7楼  2006-11-29 21:21 贼 . 夫 . 王      
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace Com.Iflytek.Tools.ExecutorFrameWork
{
    
/// <summary>
    
/// Com.Iflytek.Tools.ExecutorFrameWork以及Com.Iflytek.Tools.Executor名空间下所有对象的异常基类。
    
/// </summary>

    [global::System.Serializable]
    
public class ExecutorException : ApplicationException
    
{
        
public ExecutorException() { }
        
public ExecutorException(string message) : base(message) { }
        
public ExecutorException(string message, Exception inner) : base(message, inner) { }
        
protected ExecutorException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context)
            : 
base(info, context) { }
    }



    
/// <summary>
    
/// 异常的处理类。strategy pattern。
    
/// </summary>

    public class ExWrapper
    
{
        
public delegate T CodeBody<T>();

        
/// <summary>
        
/// T不能为Void类型。郁闷。
        
/// </summary>

        public delegate void CodeBodyForVoid();


        
/// <summary>
        
/// 记录日志后不抛出异常。
        
/// </summary>
        
/// <param name="code">代码段。</param>

        public static T SilentException<T>(CodeBody<T> code)
        
{
            
try
            
{
                
return code();
            }

            
catch (Exception ex)
            
{
                
try
                
{
                    Trace.TraceError(ex.ToString());
                }

                
catch
                
{ }
                
return default(T);

            }

        }


        
/// <summary>
        
/// 记录日之后不抛出异常。
        
/// </summary>
        
/// <param name="code"></param>
        
/// <param name="exFormatter"></param>

        public static T SilentException<T>(CodeBody<T> code, string exFormatter,params object[] args)
        
{
            
try
            
{
                
return code();
            }

            
catch (Exception ex)
            
{
                
try
                
{
                    Trace.TraceError(
string.Format("{0}异常信息如下:{1}详细信息:{2}",
                        
string.Format(exFormatter, args),
                        ex.Message, ex));
                }

                
catch
                
{
                }

                
return default(T);
            }

        }


        
/// <summary>
        
/// 记录日志后不抛出异常。用于无返回值的代码段。由于Void类型不可在C#中直接调用,对无返回值的方法必须单独写。郁闷。
        
/// </summary>
        
/// <param name="code">代码段。</param>

        public static void SilentExceptionForVoid(CodeBodyForVoid code)
        
{
            
try
            
{
                code();
            }

            
catch (Exception ex)
            
{
                
try
                
{
                    Trace.TraceError(ex.ToString());
                }

                
catch
                
{ }
            }

        }


        
/// <summary>
        
/// 记录日志后不抛出异常。用于无返回值的代码段。由于Void类型不可在C#中直接调用,对无返回值的方法必须单独写。郁闷。
        
/// </summary>
        
/// <param name="code"></param>
        
/// <param name="exFormatter"></param>

        public static void SilentExceptionForVoid(CodeBodyForVoid code, string exFormatter, params object[] args)
        
{
            
try
            
{
                code();
            }

            
catch (Exception ex)
            
{
                
try
                
{
                    Trace.TraceError(
string.Format("{0}异常信息如下:{1}详细信息:{2}",
                        
string.Format(exFormatter, args),
                        ex.Message, ex));
                }

                
catch
                
{
                }

            }

        }


        
/// <summary>
        
/// 包装异常。
        
/// </summary>
        
/// <typeparam name="T">所包装代码的返回类型。</typeparam>
        
/// <param name="code">代码段。</param>
        
/// <returns>返回值。</returns>

        public static T ThrowWrapped<T>(CodeBody<T> code)
        
{
            
try
            
{
                
return code();
            }

            
catch (Exception ex)
            
{
                
throw new ExecutorException("", ex);
            }

        }


        
/// <summary>
        
/// 包装异常。带异常时附加的信息。
        
/// </summary>
        
/// <typeparam name="T">所包装代码的返回类型。</typeparam>
        
/// <param name="code">代码段。</param>
        
/// <param name="exFormatter">异常附加信息格式化字符串</param>
        
/// <param name="args">异常附加信息参数。</param>
        
/// <returns>返回值。</returns>

        public static T ThrowWrapped<T>(CodeBody<T> code, string exFormatter, params object[] args)
        
{
            
try