注:去年写的一篇文章了,现在把它贴出来,以做参考
这里是
示例代码
利用反射解决QueryString和Session中的参数绑定问题
一. 前言
本文主要译自网上的一篇文章(http://www.codeproject.com/aspnet/WebParameter.asp),自己又作了一些改进,因此形成了这篇心得。
二. 简介:
本文介绍了在ASP.NET页面对象中利用元数据自动从Page.Request对象的QueryString中填充页面的变量和属性的策略.
三. 问题的提出
当你对ASP.NET页面进行参数化时,比如:从Request.QueryString(GET)或Request.Form(POST)中获取参数,你需要花大量的时间写类似以下的代码:
protected string FirstName


{
get
{
return Request.QueryString["FirstName"];
}
}
但是你必须处理潜在的FirstName为null值是的情况,因此你可能会通过如下的代码提供一个缺省值

protected static string IsNull(string test, string defaultValue)
{
return test==null ? defaultValue : test;
}

protected string FirstName_NullSafe
{

get
{ return IsNull(Request.QueryString["FirstName"],""); }
}
对于非字符串类型,你也可以通过稍微修改以上代码来决定当参数为null时是提供一个缺省值还是抛出一个异常,只是要用到Convert.ToXXX()函数

protected int CustomerID
{

get
{
object o=Request.QueryString["CustomerID"];
if (o==null)//如果为空,则抛出异常
{
throw new ApplicationException("Customer ID is required to be passed");
}
else
{

try
{
//如果不空,转换成Int32型
return Convert.ToInt32(o,10);

}
catch(Exception err)
{
throw new ApplicationException("Invalid CustomerID", err);
}
}
}
}
因此,在Page_Load函数里你可能会写如下的代码进行参数初始化

private void Page_Load(object sender, System.EventArgs e)
{
string o;
// 提供一个初始值
FirstName2 =IsNull(Request.QueryString["FirstName"], "");
//确保该值不为空,否则抛出异常
o =Request.QueryString["CustomerID"];
if (o==null)
throw new ApplicationException("Customer ID is required to be passed");
else

try
{//如果转换类型不正常,抛出异常
CustomerID2 = Convert.ToInt32(o,10);

}
catch(Exception err)
{
throw new ApplicationException("Invalid CustomerID", err);
}
}
小结:
当你在处理从Request.QueryString或Request.Form读取参数时,有以下的固定模式
- 从
Request.QueryString (或 Request.Form)中检索值,
- 当检索的值为空时抛出异常或提供一个缺省值
- 将检索到的值转换成合适的数据成员(field)或属性(property)
- 如果检索值不能正确转换类型,抛出一个异常或提供一个缺省值
四. 解决方案:声明性参数绑定
l 表现形式:
一个解决的方案是使用元数据(metadata),并让一些函数执行实际的工作
比如说以下形式:
[WebParameter()]
protected string FirstName;
//如果没有提供参数,则表示查找和FirstName同名的关键字,
//即QueryString[“FirstName”],
[WebParameter("Last_Name")]
protected string LastName;
//表示从QueryString中查找"Last_Name"的变量值
//即QueryString[“Last_Name”]
[WebParameter(IsRequired=true)]
protected int CustomerID;
//表示如果QueryString[“CustomerID”]返回空值,则抛出异常
可选的构造函数提供了从Request.QueryString中查找参数的关键字,IsRequired属性决定了当该参数缺失时是否抛出异常。
l 思路
本解决方案的思路是,利用反射来检索到附加在变量上的元数据,然后根据该元数据的属性决定如何对变量进行存取,其存取模式采用如第2节(《问题的提出》)最后一部分小结里的模式,只是改成了由程序自动判断进行。
1、 检索元数据属性
如前所述,当先定义一个从System.Attribute派生的元数据类WebParameterAttribut,
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple=false, Inherited=true)]
public class WebParameterAttribute : Attribute


{
public int ParamName;
public string DefaultValue

{

get
{ return _default ; }

set
{ _default=value ; }
}
}
注:AttributeUsageAttribute使用说明
说明:
[WebParameter("Last_Name")]
protected string LastName;
当以上面形式使用自定义的属性类时,实际上等与是生成了一个和LastName的类型对象LastName.GetType()相关联的WebParameterAttribute类的对象,通过LastName.GetType()对象可以检索到WebParameter对象的一些方法成员、数据成员以及属性等;
我们可以定义WebParameterAttribute类的静态方法,WebParameterAttribute.SetValues(object target, System.Web.HttpRequest request)完成自动初始化某个页面的所有参数,该方法有两个参数:target表示将被自动进行参数化的对象,例如可以是某个页面对象(Page);request是在某个页面对象的初始化时传来的Request对象;后面我们会详细解释SetValues方法的设计
示例如下面粗体部分所示:
在上面的示例中,静态方法WebParameterAttribut.SetValues先获取this指针代表的Page对象的类型对象this.GetType(),然后用该类型对象获取Page对象的所有变量和属性的信息,即可以获得并操纵Page对象的FirstName,LastName和CustomerID,也包括TestNum。然后SetValues方法检查每个检索到的变量和属性,看有没有关联WebParameter对象,相对来说,数据成员TestNum就没有关联WebParameter对象。
当SetValues检测到变量(field)或属性(property)关联有WebParameter对象时,该方法会检索和变量或属性向关联的WebParameter对象的具体属性,比如说:
[WebParameter("Last_Name")]
protected string LastName;
生成了一个WebParameter对象,并传递给构造函数一个参数”Last_Name”,SetValues方法会检测出和string LastName相关联的WebParameter中包含的“Last_Name”并将其作为要在QueryString中检测的变量的名字。
l 代码解析
下面是SetValues的具体实现:
² 变量及属性定义
² SetValues方法
从request中检索特定值并设定target中指定变量和属性的值
public static void SetValues(object target, System.Web.HttpRequest request)


{//传入的target对象可以是Page对象,request可以是Page.Request对象
//获取target的类型信息
System.Type type =target.GetType();
//获取target公开的、实例化后的成员信息
MemberInfo[] members= type.GetMembers(BindingFlags.Instance |
BindingFlags.Public|
BindingFlags.NonPublic);
//Instance:只对非静态的成员查找;
//Public:只对具有公开访问属性的成员进行查找
//在和Instance或static联用时,
//必须指定NonPublic或Public,否则返回空值
foreach(MemberInfo member in members)

{
if((member is FieldInfo) || (member is PropertyInfo))

{//对变量和属性,设置其初始值
SetValue(member, target, request);
}
}
}
² SetValue方法
根据member对象的类型是变量(Field)或属性(Property