您现在的位置:中国下载站学院中心网络编程ASP.net教程Asp.Net开发技巧 → 文章列表

一种基于.Net 2.0的另类AOP

作者:佚名  来源:不详  发布时间:2006-12-29 0:18:30   

减小字体 增大字体

 
 
说这种方法是AOP其实有些牵强,只能说是多少带出了一点面向切面编程的影子。不过它的实现方法很简洁,不需要任何复杂的库的支持,唯一需要的就是C# 2.0,使用的关键技术是泛型编程和匿名委托。

  我的需求是这样的:比如有一个函数,要从一个配置中取得一个整数值:

  int GetIntValue()

  {

   try

   {

   return Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["SomeSetting"]);

   }

   catch

   {

   return 20;

   }

  }

  这里涉及了以下几点问题

  1 方法从一个配置文件中读取值,这个值在配置文件中也许不存在

  2 也许在配置文件中存在,但它却不是一个有效的整数

  3 基于1、2,需要为它做异常处理

  4 当异常发生时,需要为它取一个缺省值


  也许我要从配置文件里取很多值,涉及到各种类型,或者是从别处取值,但也涉及到类型转换等需要异常处理的情况,这时我们发现,这里“异常处理”成了这类方法的一个“方面”,如果使用AOP的方法,应该对这类方法进行拦截,并进行统一的异常处理。

  利用C#2.0,我们可以把这个拦截工作变得很简单。

  第一步,让它支持异常处理:

  我们来定义一个统一的方法,使它可以进行异常处理:

 public T GetValue()

  {

   try

   {

   return SomeMethod()

   }

   catch

   {}

  }

  这里我们使用了C#2.0的泛型特性,使它可以返回任何类型的结果,并且带有编译时类型安全检查,不像C# 1.x那样,返回一个object,仍需要检查object的类型,特别是对于简单类型,如int,则免去了装箱过程。

  但这个方法有个很明显的问题,就是当异常发生时,catch的部分并没有返回值,从而导致它编译不能通过。注意到当发生异常时应该返回一个缺省值,而缺省值和返回值的类型必然是相同的,所以可以为它添加一个参数作为缺省值:

  第二步,添加缺省值:

  public T GetValue(T defaultValue)

  {

   try

   {

   return SomeMethod()

   }

   catch

   {

   return defaultValue;

   }

  }


我想你早就提出了一个问题,那就是代码中的“SomeMethod”是什么呢?从逻辑上讲这里应该是我们真正要取得想要的值的地方,而取值的办法是随需求而变化的,最佳的处理方式就是留给程序员自己来实现,那么要实现这种操作,最合适的方法就是使用委托(delegate)了:

  第三步 加入委托:

  public delegate T GetValueDelegate();

  public T GetValue(GetValueDelegate dele, T defaultValue)

  {

   try

   {

   return dele();

   }

   catch

   {

   return defaultValue;

   }

  }

  这里委托也使用了泛型,使得它只能返回和我们需要的类型相一致的变量。

  这回看着舒服多了。但用过C# 1.x的人都知道delegate那冗长的语法是多么的烦人,并且还有一个问题,就是如果在取值的过程中需要从外界取参数,而参数的个数、类型都是不确定的,那么这个delegate这样定义还合适吗?要不要像C# 1.X那样,定义一个object[]作为参数呢?答案是不必的,因为C# 2.0中我们可以使用匿名委托,并且在匿名委托中我们可以方便的使用它的父作用域中的变量,就像使用本地的变量一样:

  第四步,使用我们的AOP:

   int myValue = GetValue(delegate() {

   return Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["SomeSetting"]);

   }, 20);

  这里已经通过参数20可以推断出模板参数T的类型,所以不需要再指定模板参数了。现在再使用的时候完全可以不必处理try...catch烦人的语法,只管去取值就可以了 :)



  类似的应用还可以在访问数据库时。例如用DataReader访问数据库,必须要刻用完了Reader和Connection需要关闭,并且需要处理各种异常情况。用类似的方法可以写出比较方便的函数:

 public delegate T TryExecuteReaderDelegate(SqlDataReader reader);

  public T TryExecuteReader(SqlCommand command, TryExecuteReaderDelegate dele, T defaultValue)

  {

  command.Connection = conn;

  SqlDataReader reader = null;

  try

  {

  conn.Open();

  reader = command.ExecuteReader();

  return dele(reader);

  }

  catch

  {

  return defaultValue;

  }

  finally

  {

  if(reader != null && !reader.IsClosed)

  reader.Close();

  if(conn != null && conn.State != ConnectionState.Closed)

  conn.Close();

  }

  }
  使用:

  SqlCommand command = new SqlCommand("select xxxx");

  command.Parameters.AddWithValue("@paramName", value);

  String s = TryExecuteReader(command, delegate(SqlDataReader reader)

  {

  reader.Read();

  return reader.GetString(0);

  }, "haha");

  这样一来,使用的时候要方便很多,再也不用考虑连接是否关闭、是否处理了异常情况等问题:正常的时候返回想要的结果,异常的时候返回缺省值。

在百度中搜索更多一种基于.Net 2.0的另类AOP相关网页 转贴于:中国下载站

  • 上一篇文章:设置页面buffer引出来的问题
  • 下一篇文章:ASP.NET服务器控件之控件状态
  • 阅读统计:[]
  • 中国下载站】【设为主页】【收藏本页】【打印本文】【回到顶部】【关闭此页

    相关文章
    文章评论(评论内容只代表网友观点,与本站立场无关!)

    用户名: 查看更多评论

    分 值:100分 85分 70分 55分 40分 25分 10分 0分

    内 容:

             (注“”为必填内容。) 验证码: 验证码,看不清楚?请点击刷新验证码


    设为首页 - 关于我们 - 广告服务 - 网站地图 - 加入收藏 - 网站声明 - 网站帮助 - 友情链接

    • Copyright (C) 2006-2008 www.cndownz.com All Rights Reserved.
      中国下载站 版权所有. 粤ICP备05141802号. 对本站有任何建议、意见或投诉,请来信:cndownzcom@yahoo.com.cn.
      喜欢中国下载站(cndownz.com),请把中国下载站(cndownz.com)告诉你QQ上的5位好友,多谢支持!