逆水行船

别人的天堂,是我的异乡;无端的繁华,倍添我的惆怅

 

Attribute学习:SqlCommandGenerator

using System;
using System.Reflection;
using System.Data;
using System.Data.SqlClient;
using Debug = System.Diagnostics.Debug;
using StackTrace = System.Diagnostics.StackTrace;

namespace WebApplication1
{
 /// <summary>
 /// 本类主要用于根据属性生成带参数数组的Command对象。
 ///我存在一个问题就是利用属性,是否对程序的效率有很大的影响。
 /// 还有,我如何把属性应用到某个类的property或字段中,而且能很方便的读取这些变量?

 /// </summary>
 public sealed class SqlCommandGenerator
 {
  // 静态只读属性,定义用于返回值的参数名称
  public static string ReturnValueParameterName
  {
   get
   {
    return "RETURN_VALUE";
   }
  }

  // 静态只读属性,用于不带参数的存储过程
  public static object[] NoValues
  {
   get
   {
    return new object[] {};
   }
  }

  // 私有构造器,不允许使用无参数的构造器构造一个实例
  private SqlCommandGenerator()
  {
   throw new NotSupportedException();
  }

  /// <summary>
  /// 根据传入的参数,生成一个Command对象。
  /// </summary>
  /// <param name="connection">数据库联接组件</param>
  /// <param name="method"> 发现方法的特性并提供对方法元数据的访问</param>
  /// <param name="values">参数数组值集合</param>
  /// <returns>Command镀锡iang</returns>
  public static SqlCommand GenerateCommand(SqlConnection connection, MethodInfo method, object[] values)
  {
   //如果没有指定方法名称,从堆栈帧得到方法名称
   //  StackTrace:表示一个堆栈跟踪,它是一个或多个堆栈帧的有序集合。
   //  GetFrame: 获取指定的堆栈帧。
   //  GetMethod: 获取在其中执行帧的方法。
   //  这儿不懂,就囫囵吞枣的放在这儿。
   if (method == null)
   {
    method = (MethodInfo)(new StackTrace().GetFrame(1).GetMethod());
   }

   // 获取方法传进来的SqlCommandMethodAttribute
   // 为了使用该方法来生成一个Command对象,要求有这个Attribute。
   SqlCommandMethodAttribute commandAttribute = (SqlCommandMethodAttribute)Attribute.GetCustomAttribute(method, typeof(SqlCommandMethodAttribute));

   Debug.Assert(commandAttribute != null);
   Debug.Assert(commandAttribute.Commondtype == CommandType.StoredProcedure ||
    commandAttribute.Commondtype == CommandType.Text);

    // 创建一个SqlCommand对象,同时通过指定的attribute对它进行配置。
    SqlCommand command = new SqlCommand();
   command.Connection = connection;

   // command类型
   command.CommandType = commandAttribute.Commondtype;

   // 获取command的文本,如果没有指定,那么使用方法的名称作为存储过程名称
   if (commandAttribute.CommandText.Length == 0)
   {
    Debug.Assert(commandAttribute.Commondtype == CommandType.StoredProcedure);
    command.CommandText = method.Name;
   }
   else
   {
    command.CommandText = commandAttribute.CommandText;
   }

   // 调用GeneratorCommandParameters方法,生成command参数,同时添加一个返回值参数
   GenerateCommandParameters(command, method, values);

   // 给参数数组添加一个参数“RETURN_VALUE”
   command.Parameters.Add(ReturnValueParameterName, SqlDbType.Int).Direction = ParameterDirection.ReturnValue;

   return command;
  }
  private static void GenerateCommandParameters(
   SqlCommand command, MethodInfo method, object[] values)
  {
   // 得到该方法所有的参数,通过循环一一进行处理。
   ParameterInfo[] methodParameters = method.GetParameters();
   int paramIndex = 0;

   foreach (ParameterInfo paramInfo in methodParameters)
   {
    // 忽略掉参数被标记为[NonCommandParameter ]的参数
    //
    if (Attribute.IsDefined(paramInfo, typeof(NonCommandParameterAttribute)))
    {
     continue;
    }

    // 获取参数的SqlParameter attribute,如果没有指定,那么就创建一个并使用它的缺省设置。
    SqlParameterAttribute paraAttribute = (SqlParameterAttribute)Attribute.GetCustomAttribute(paramInfo, typeof(SqlParameterAttribute));

    if (paraAttribute == null)
    {
     paraAttribute = new SqlParameterAttribute();
    }

    //使用attribute的设置来配置一个参数对象。使用那些已经定义的参数值。如果没有定义,那么就从方法
    // 的参数来推断它的参数值。
    SqlParameter sqlParameter = new SqlParameter();

    // 如果属性中名称有指定,用属性名称
    if (paraAttribute.IsNameDefined)
    {
     sqlParameter.ParameterName = paraAttribute.Name;
    }
     // 否则,用参数名称
    else
    {
     sqlParameter.ParameterName = paramInfo.Name;
    }

    // 参数名称是否以@开头,如果不是,自动添加@
    if (!(sqlParameter.ParameterName.StartsWith("@")))
    {
     sqlParameter.ParameterName = "@" + sqlParameter.ParameterName;
    }

    // 参数是否指定参数类型,如果指定,用属性中的类型
    if (paraAttribute.IsTypeDefined)
    {
     sqlParameter.SqlDbType = paraAttribute.ParamType;
    }

    // 属性中是否指定参数大小,如果指定,用参数中的大小
    if (paraAttribute.IsSizeDefined)
    {
     sqlParameter.Size = paraAttribute.Size;
    }

    // 属性中是否指定参数的范围,如果指定,用参数中的范围。
    if (paraAttribute.IsScaleDefined)
    {
     sqlParameter.Scale = paraAttribute.Scale;
    }

    // 属性中是否指定参数的精度,如果指定,用参数中的精度。
    if (paraAttribute.IsPrecisionDefined)
    {
     sqlParameter.Precision = paraAttribute.Precision;
    }

    // 属性中是否指定参数的方向,如果指定,用参数中定义的方向
    if (paraAttribute.IsDirectionDefined)
    {
     sqlParameter.Direction = paraAttribute.Direction;
    }
    else
    {
     // 参数是否是引用,如果是引用,则设置为Output,或InputOutput
     if (paramInfo.ParameterType.IsByRef)
     {
      sqlParameter.Direction = paramInfo.IsOut ? ParameterDirection.Output : ParameterDirection.InputOutput;
     }
      // 否则,设置为Input
     else
     {
      sqlParameter.Direction = ParameterDirection.Input;
     }
    }

    // 检测是否提供的足够的参数对象值
    Debug.Assert(paramIndex < values.Length);

    sqlParameter.Value = values[paramIndex];
    command.Parameters.Add(sqlParameter);

    paramIndex++;
   }

   // 检测是否有多余的参数对象值
   Debug.Assert(paramIndex == values.Length);
  }
 }
}

posted on 2005-07-26 11:49  荣-  阅读(345)  评论(0)    收藏  举报

导航