导读:
Web开发做得多了,总觉得是体力活,于是搞些代码让自己脱离无聊的Coding吧(是脱离“无聊的”Coding,不是脱离无聊的“Coding”)。
初级阶段
为每个QueryString写转换的代码,针对不同的类型,进行转换和错误处理。
中级阶段
写了一个函数,专门做转换(1.1里写的):
/// /// Convert query string to parameter.
/// ///
Name of query string ///
Default value of query string ///
If the query string is required
private object ConvertParameter(string name, object defaultValue, bool isRequired)
高级阶段
昨天写的,第一次发文,大家拍砖吧:
主要是用了Attribute和反射的思想,首先给变量设置HttpQueryString的属性,绑定上相应的QueryString,然后由Page基类来读取相应的QueryString信息。
属性这么写(HttpQueryStringAttribute.cs):
using System; namespace GooKuu.Framework.Web
{
/// /// Specifies a field for a query string.
///
[AttributeUsage(AttributeTargets.Field)]
public sealed class HttpQueryStringAttribute : Attribute
{
private string _name;
private object _defaultValue;
private bool _isRequired;
/// /// Constructor. The query string must be provided.
/// ///
Name of the query string
public HttpQueryStringAttribute(string name)
{
_name = name;
_defaultValue = null _isRequired = true }
/// /// Constructor. If the query string is not be provided, using the default value.
/// ///
Name of the query string ///
Default value of the query string which is not provided
public HttpQueryStringAttribute(string name, object defaultValue)
{
_name = name;
_defaultValue = defaultValue;
_isRequired = false }
/// /// Name of the query string.
///
public string Name
{
get { return _name; }
}
/// /// Default value of the query string which is not provided.
///
public object DefaultValue
{
get { return _defaultValue; }
}
/// /// Indicates if the query string must be provided.
///
public bool IsRequired
{
get { return _isRequired; }
}
}
}
页面基类是这样的(PageBase.cs):
using System; using System.Reflection; using System.Web; using System.Web.UI; namespace GooKuu.Framework.Web
{
/// /// Base class of all pages.
///
public class PageBase : Page
{
/// /// Override OnLoad method of base class.
/// ///
protected override void OnLoad(System.EventArgs e)
{
ParameterInitialize();
base.OnLoad(e);
}
/// /// Initialize parameters according to query strings.
///
private void ParameterInitialize()
{
// Get Type of current page class.
Type type = this.GetType();
// Get all fields of current page class.
FieldInfo[] fields = type.GetFields();
foreach (FieldInfo field in fields)
{
// Get HttpQueryStringAttribute of current field.
HttpQueryStringAttribute attribute = (HttpQueryStringAttribute)Attribute.GetCustomAttribute(field, typeof(HttpQueryStringAttribute));
// If has HttpQueryStringAttribute, this field is for a query string.
if (attribute != null)
{
SetField(field, attribute);
}
}
}
/// /// Set field according to the HttpQueryStringAttribute.
/// ///
The field will be set ///
The attribute of current field
private void SetField(FieldInfo field, HttpQueryStringAttribute attribute)
{
// The query string must be provided.
if (attribute.IsRequired)
{
if (Request.QueryString[attribute.Name] != null)
{
SetFieldValue(field, this, attribute.Name, field.FieldType);
}
else {
throw new Exception(string.Format("Query string /"{0}/" is required", attribute.Name), new NullReferenceException());
}
}
// If the query string is not be provided, using the default value.
else {
if (attribute.DefaultValue == null || field.FieldType == attribute.DefaultValue.GetType())
{
if (Request.QueryString[attribute.Name] == null || Request.QueryString[attribute.Name] == string.Empty)
{
field.SetValue(this, attribute.DefaultValue);
}
else {
SetFieldValue(field, this, attribute.Name, field.FieldType);
}
}
else {
throw new Exception(string.Format("Invalid default value of query string /"{0}/"({1})", attribute.Name, field.Name), new NullReferenceException());
}
}
}
/// /// Set the value of current field according to the query string.
/// ///
The field will be set ///
The object whose field value will be set ///
The name of query string ///
The type to be converted
private void SetFieldValue(FieldInfo field, object obj, string name, Type conversionType)
{
try {
// Set field value.
field.SetValue(obj, Convert.ChangeType(Request.QueryString[name], conversionType));
}
catch (Exception ex)
{
throw new Exception(string.Format("The given value of query string /"{0}/" can not be convert to {1}", name, conversionType), ex);
}
}
}
}
在页面里,这样写就OK了(Default.aspx.cs):
using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using GooKuu.Framework.Web; public partial class _Default : PageBase
{
/// /// Name 是Query String的名字,"Anonymous"是缺省值。
/// 如果没有提供这个Query String,就采用缺省值。
///
[HttpQueryString("Name", "Anonymous")]
public string name;
/// /// UserId 是Query String的名字,不提供缺省值。
/// 如果没有提供这个Query String或者提供的格式不正确导致转换失败,都会抛出异常。
///
[HttpQueryString("UserId")]
public int userId;
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(string.Format("Name is {0}
", name));
Response.Write(string.Format("UserId is {0}
", userId));
}
}
posted on 2006-01-16 11:01 Ariel Y.阅读(3042) 评论(22) 编辑 收藏引用收藏至365Key所属分类: Technology
评论:
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 11:21 | rexsp
// Get all fields of current page class.
FieldInfo[] fields = type.GetFields();
感觉没有必要把所有的栏位读出来循环,只读那些加载了自定义的Attribute的就好了吧 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 11:33 | Ariel Y.
@rexsp
我也是这么想的,可是我不知道GetFields应该传什么参数才能得到只加载了自定义的Attribute的Field。能指教一下用哪个BindingFlags枚举吗? 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 13:24 | kwklover
提两个问题:
1,写.net的文章,是否应该注明适用于.net2.0还是.net1.x,毕竟.net发展已经5年多了,平台版本之间具有一定差异性 ?
2,是否应该说明这种方法有什么好处和坏处 ?
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 13:41 | Ariel Y.
@kwklover
谢谢你的意见,确实应该写清楚的。
我没有注明,应该是通用的:)因为没有用到什么.net 2.0的新特性,不过我确实是在VS 2005里写的。
好处么,应该是方便吧,减少我们的代码量,脱离一部分枯燥重复的Coding。
坏处么,应该是性能问题吧,但是我也不知道用反射会对性能造成多大影响,有时间测试一下;这里还希望高手指点一下性能的影响。
好多朋友说看不懂:(其实本来这篇文章就不是什么入门文章,也不是学习新知识,只是介绍我的一个思路,没有教大家写代码。所以,没有做过多解释。注释已经写的很清楚了。
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 14:15 | mkimtaehee
不懂,未来应该要学习的。(最近到处听说动态类构造啊,反射什么的)
我的技术还停留在WINFROM的数据库 增删改查 真觉得自己低级 汗~~~~~~~~~~~~~~~~~~~~~ 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 15:23 | 午夜寻欢
终于学习到怎么用自定义属性了!
可我还是不太明白你这些代码要完成的功能是什么?
难道就是简单的类型转换吗?
有这个必要写这么长的代码吗? 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 17:01 | Ariel Y.
我这段代码可以省去以后在页面里处理Query String的代码。
比如以前写:
public Guid userId;
public int count;
public void Page_Load()
{
try
{
userId = new Guid(Request.QueryString["UserId"].ToString());
}
catch
{
throw new Exception();
}
if(Request.QueryString["Count"] == null || Request.QueryString["Count"].ToSTring() = string.Empty)
{
count = 0;
}
else
{
try
{
count = Convert.ToInt32(Request.QueryString["Count"].ToString());
}
catch
{
throw new Exception();
}
}
}
现在只要写:
[HttpQueryString("UserId")]
public Guid userId; // 这里的字段不能是private的。
[HttpQueryString("Count", 0)]
public int count; // 这里的字段不能是private的。
就可以了。
难道你只看到了类型转换?
怎么说也是根据定义的变量的数据类型自动转换对应的QueryString吧?呵呵。
我觉得“有这个必要写这么长的代码吗?”这种思想是很有害的一种想法。
假设我这个代码有100行,我一次就写这么多了,以后每次就只有几行。如果不这么干(我是说,不提炼一些东西出来),你每页都要写,假设20行,你写一个项目我想也不仅仅只有5个页面吧?你看,做一个项目我就比你快:)
就像我开头说的,做一些枯燥重复的开发是没有意义的。永远是软件工人。
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 17:47 | lee_j
我看完楼主的代码后,发现从设计上有一个失误.PageBase类是实现代码复用的关键,而用自定义Atribute反而有画蛇添足的感觉.正如楼主所说利用反射机制令代码的效率降低.
我想有两种方法去改进
1.把PageBase的SetField功能移到HttpRequestStringAttribute类中;
2.不用自动义Attribute,改成Interface.PageBase去实现Interface,而不用反射机制.
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 22:35 | 木野狐
我认为这种实现方法过于麻烦。我的实现通常都是这样的:
在一个公共的方法类里面这样写,
public class Util {
private Util() {}
// 从 querystring 集合中安全的取得一个 string. (总是不会有 null,所以叫做 'Safe')
public static string GetStringSafeFromQueryString(Page page, string key) {
string value = page.Request.QueryString[key];
return (value == null) ? string.Empty : value;
}
// 在上述基础上,实现几个常用类型的获取方法。
public static int GetInt32SafeFromQueryString(Page page, string key, int defaultValue) {
string value = GetStringSafeFromQueryString(page, key);
int i = defaultValue;
try {
i = int.Parse(value);
} catch {}
return i;
}
// double 的实现
public static double GetDoubleSafeFromQueryString(Page page,
string key, double defaultValue) {
string value = GetStringSafeFromQueryString(page, key);
double d = defaultValue;
try {
d = double.Parse(value);
} catch {}
return d;
}
// 同理可以写出 float, ... 的实现
}
在我的任何页面里面,要获取 querystring 的时候,只要这样就可以了:
比如我要获取一个 string:
string name = Util.GetStringSafeFromQueryString(this, "name");
if (name.Length >0) {
// 进行正常的处理...
} else {
// 不处理。
}
获取 int:
int id = Util.GetInt32SafeFromQueryString(this, "id", 0);
处理 double, float 等等方法完全一样。
我认为就一个 QueryString 的处理没必要上升到反射的高度,其实有时候反过来想想,实现的那么复杂也许会丧失一定的灵活性。比如我某个值忽然要改为从 Form 里面得到呢?从 Session 得到呢?这时候就可以比较出哪种做法更适合敏捷的适应需求。
页面里的 QueryString 的处理,之所以大家都很痛恨手工写编码,无非是因为这么几点:
1. 需要判断是否 == null 才敢用 .ToString(), 很不爽。稍微不注意,就会抛出异常导致页面错误。
2. 整形,double 等值类型从 QueryString 里面获取的时候,不知道是否为合法的数值,因此 Parse 的时候总是要写重复的处理异常的代码。
归纳一下,其实,一个页面用下列语法获取一个 QueryString 的时候,他得到的是如下东西:
(假设用 string name = Request.QueryString["name"]; 来获取。)
1. ...test.aspx 得到 null
2. ...test.aspx?name= 得到 ""
3. ...test.aspx?name=abc 得到 "abc"
我认为 1 和 2 的情况实际上从程序处理上来讲,是没有区别的。因此判断 null 没有必要,我们每次都将 null 的值自动让他转为 string.Empty 应该是比较安全的做法。
基于上述理由,我觉得如我上面所写的简单的工具类,就可以轻量级的解决安全的读取 QueryString 的问题。
有不对的地方,请大家多多指教。 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 23:35 | 双鱼座
呵呵,这种方式与我从前做权限控制的方式几乎一样,用来处理QueryString的确小题大作了一点。两处缺陷:一是污染了Page类的代价太大了一点(自然木野孤的方案清洁一点);二是必须定义一个Field并且要加上自定义标签并且要与QueryString键字符串相吻合。
我在控制权限的时候,那个自定义标签是抽象的,加在Page固有的Field上(通常是页面中静态的Control),对于不同的Control根本不同的权限采取不同的策略进行不同的处理,具有充分的可扩充性,这样污染Page类就物有所值。 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-17 09:19 | Terrylee
楼主的设计思想很好……
可是为了QueryString花这么大的代价,值得吗? 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-17 10:12 | Ariel Y.
@各位
有人说这方法画蛇添足,有人说麻烦有,人说污染,有人说小题大做。我的想法呢,很简单,前边已经说过,我是为了少写代码,越少越好,呵呵。让机器多干点,人少干点,没错吧?其实,我也有个前提,做的一些项目都是小系统,在局域网内运行,一个站点跑一个Xeon的Server。我何苦折磨自己去讨好Xeon呢?麻烦?谁麻烦?我们麻烦还是机器麻烦?机器麻烦?干吗不麻烦它?几个G的脑瓜天天在那儿傻着!
对于Large-scale网站,我才不会用这个,性能即过程!
这么多高人关注,谢谢,呵呵。下边的言语如果多有得罪,还请见谅!
@lee_j
第一点,我和你想的一样,但是我不会,能指点一下吗?在Attribute里可以读到被它绑定的对象吗?我没找到方法。
第二点,没明白你的意思,Interface来做什么?但是好像对于我这篇文章就跑题了,我这篇文章叫一行代码搞定QueryString,呵呵。
请指教!
@木野狐
你这类代码的思想,正是我现在用的。不过我觉得完全没有必要传那个Page进去,用HttpContext.Current.Request.QueryString[]就可以读了
而且现在我有两种实现,一个是你这种Utility类,一种更OO的方法是自己实现一个QueryString类作为Page基类的成员,用的时候:this.QueryString.GetInt32(......);
@双鱼座
你的文章我很喜欢,但是先说一句得罪了!我有些出离愤怒了!
第一,怎么就叫代价大了?怎么就小了?
第二,必须定义一个Feild..............................。难道其他方式不用定义变量吗?其他方式不更是要写代码吗?其他方式不需要与QueryString键字符串相吻合吗?难道一行代码都不用写就让我实现吗?我可做不到:(
为什么你的污染就值?怎么污染就不值?太主观了吧?我地孩儿也是孩儿啊,555555。
@Terrylee &All
其实我这篇文章讨论的问题真是芝麻绿豆大点子的事儿,纯属是玩些技术把戏,我也就是写着玩儿玩儿。但是真的写好了,并且简单好用,何乐而不用呢?
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-17 10:27 | 木野狐
楼主的出发点很好,从技术的角度讲也是一种很有益的练习,不过双鱼座所说的“污染”其实只是从 OO 思想的角度来讲的,并没有任何贬低的意思啊。还望楼主不要误解了。常常我们会说“污染”一个名称空间之类的说法,其实说的不过是某个类,或者某个名称空间下干了比它应有的职责更多的事情而已,呵呵。
关于我的回复,昨天回复完后,也贴到自己的 blog 上去了:
http://rchen.cnblogs.com/archive/2006/01/16/318561.html
根据 stone790809 网友的建议,我现在已经改进了做法,不再传递 Page 类作为参数了,这个跟你的建议是一致的 :)
其实并非我不知道 HttpContext.Current.Request 这个用法,只是平常传递 Page 对象传惯了,写成了惯性而已,呵呵。
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-17 10:40 | Ariel Y.
@木野狐
哦,才发现,确实,从OO的角度讲,确实有污染,谢谢指正!
@双鱼座
不好意思啦。 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-17 17:13 | zkxp
什么是OO到处看到,汗一个先。。。 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-17 22:55 | sema
国外有类似思路的文章介绍,大家可以参考一下
http://www.codeproject.com/aspnet/WebParameter.asp
如果英文的看着累,也可以看看翻译的文章
http://dragon.cnblogs.com/archive/2005/03/24/125160.html
应该说这种思路还是很有意思的。但是实际对效率的影响的确需要评估。
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-18 00:22 | Ariel Y.
@sema
您的名字让我想起一句广告:“穿什么,就是什么”:)
楼上吓我一身汗,跟我的好像!我可是干巴巴想出来的,呵呵。
不过我喜欢这种说法:“但是实际对效率的影响的确需要评估”,而不是有些人(没有特指,请勿对号入座,真的):“效率很差,效率不高”。
知道读数据DataReader比DataAdpater+DataSet快多少吗?总有人说快好多,实际的评测结果好像是14%-18%(参考自“DEV411 ASP.NET: Best Practices For Performance - Stephen Walther www.SuperexpertTraining.com - TechEd 2004”)
@zhxp
OO means Object-Oriented Programming Concepts
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-19 12:35 | torome
看了高人的文章.
自己感觉还有很多要学习。.
努力!~ 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-20 15:10 | Stanley Liu
搞明白自定义属性了,happying
谢谢Ariel Y. ~ 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-23 08:59 | xiao_p
能不能把鼠标特殊效果撤销掉了……
实在是难受,看得时候……
呵呵
对于文章,就没有什么好说的了,确实不错~~
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-02-14 10:00 | chating
是个好方法,但程序代码效率低. 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-04-21 08:13 | 生活被我强奸。。。
呵呵。。这么一大堆我不太明白@我来这里是谢谢你的:)。。
回复
# re: 一行代码搞定你的QueryString!(原创)2006-04-21 14:33 | Ariel Y.
谢谢。 回复
Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=1368460
本文转自
http://blog.youkuaiyun.com/jelink/archive/2006/11/05/1368460.aspx
Web开发做得多了,总觉得是体力活,于是搞些代码让自己脱离无聊的Coding吧(是脱离“无聊的”Coding,不是脱离无聊的“Coding”)。
初级阶段
为每个QueryString写转换的代码,针对不同的类型,进行转换和错误处理。
中级阶段
写了一个函数,专门做转换(1.1里写的):
///
///
private object ConvertParameter(string name, object defaultValue, bool isRequired)
高级阶段
昨天写的,第一次发文,大家拍砖吧:
主要是用了Attribute和反射的思想,首先给变量设置HttpQueryString的属性,绑定上相应的QueryString,然后由Page基类来读取相应的QueryString信息。
属性这么写(HttpQueryStringAttribute.cs):
using System; namespace GooKuu.Framework.Web
{
///
///
[AttributeUsage(AttributeTargets.Field)]
public sealed class HttpQueryStringAttribute : Attribute
{
private string _name;
private object _defaultValue;
private bool _isRequired;
///
///
public HttpQueryStringAttribute(string name)
{
_name = name;
_defaultValue = null _isRequired = true }
///
///
public HttpQueryStringAttribute(string name, object defaultValue)
{
_name = name;
_defaultValue = defaultValue;
_isRequired = false }
///
///
public string Name
{
get { return _name; }
}
///
///
public object DefaultValue
{
get { return _defaultValue; }
}
///
///
public bool IsRequired
{
get { return _isRequired; }
}
}
}
页面基类是这样的(PageBase.cs):
using System; using System.Reflection; using System.Web; using System.Web.UI; namespace GooKuu.Framework.Web
{
///
///
public class PageBase : Page
{
///
///
protected override void OnLoad(System.EventArgs e)
{
ParameterInitialize();
base.OnLoad(e);
}
///
///
private void ParameterInitialize()
{
// Get Type of current page class.
Type type = this.GetType();
// Get all fields of current page class.
FieldInfo[] fields = type.GetFields();
foreach (FieldInfo field in fields)
{
// Get HttpQueryStringAttribute of current field.
HttpQueryStringAttribute attribute = (HttpQueryStringAttribute)Attribute.GetCustomAttribute(field, typeof(HttpQueryStringAttribute));
// If has HttpQueryStringAttribute, this field is for a query string.
if (attribute != null)
{
SetField(field, attribute);
}
}
}
///
///
private void SetField(FieldInfo field, HttpQueryStringAttribute attribute)
{
// The query string must be provided.
if (attribute.IsRequired)
{
if (Request.QueryString[attribute.Name] != null)
{
SetFieldValue(field, this, attribute.Name, field.FieldType);
}
else {
throw new Exception(string.Format("Query string /"{0}/" is required", attribute.Name), new NullReferenceException());
}
}
// If the query string is not be provided, using the default value.
else {
if (attribute.DefaultValue == null || field.FieldType == attribute.DefaultValue.GetType())
{
if (Request.QueryString[attribute.Name] == null || Request.QueryString[attribute.Name] == string.Empty)
{
field.SetValue(this, attribute.DefaultValue);
}
else {
SetFieldValue(field, this, attribute.Name, field.FieldType);
}
}
else {
throw new Exception(string.Format("Invalid default value of query string /"{0}/"({1})", attribute.Name, field.Name), new NullReferenceException());
}
}
}
///
///
private void SetFieldValue(FieldInfo field, object obj, string name, Type conversionType)
{
try {
// Set field value.
field.SetValue(obj, Convert.ChangeType(Request.QueryString[name], conversionType));
}
catch (Exception ex)
{
throw new Exception(string.Format("The given value of query string /"{0}/" can not be convert to {1}", name, conversionType), ex);
}
}
}
}
在页面里,这样写就OK了(Default.aspx.cs):
using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using GooKuu.Framework.Web; public partial class _Default : PageBase
{
///
/// 如果没有提供这个Query String,就采用缺省值。
///
[HttpQueryString("Name", "Anonymous")]
public string name;
///
/// 如果没有提供这个Query String或者提供的格式不正确导致转换失败,都会抛出异常。
///
[HttpQueryString("UserId")]
public int userId;
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(string.Format("Name is {0}
", name));
Response.Write(string.Format("UserId is {0}
", userId));
}
}
posted on 2006-01-16 11:01 Ariel Y.阅读(3042) 评论(22) 编辑 收藏引用收藏至365Key所属分类: Technology

评论:
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 11:21 | rexsp
// Get all fields of current page class.
FieldInfo[] fields = type.GetFields();
感觉没有必要把所有的栏位读出来循环,只读那些加载了自定义的Attribute的就好了吧 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 11:33 | Ariel Y.
@rexsp
我也是这么想的,可是我不知道GetFields应该传什么参数才能得到只加载了自定义的Attribute的Field。能指教一下用哪个BindingFlags枚举吗? 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 13:24 | kwklover
提两个问题:
1,写.net的文章,是否应该注明适用于.net2.0还是.net1.x,毕竟.net发展已经5年多了,平台版本之间具有一定差异性 ?
2,是否应该说明这种方法有什么好处和坏处 ?
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 13:41 | Ariel Y.
@kwklover
谢谢你的意见,确实应该写清楚的。
我没有注明,应该是通用的:)因为没有用到什么.net 2.0的新特性,不过我确实是在VS 2005里写的。
好处么,应该是方便吧,减少我们的代码量,脱离一部分枯燥重复的Coding。
坏处么,应该是性能问题吧,但是我也不知道用反射会对性能造成多大影响,有时间测试一下;这里还希望高手指点一下性能的影响。
好多朋友说看不懂:(其实本来这篇文章就不是什么入门文章,也不是学习新知识,只是介绍我的一个思路,没有教大家写代码。所以,没有做过多解释。注释已经写的很清楚了。
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 14:15 | mkimtaehee
不懂,未来应该要学习的。(最近到处听说动态类构造啊,反射什么的)
我的技术还停留在WINFROM的数据库 增删改查 真觉得自己低级 汗~~~~~~~~~~~~~~~~~~~~~ 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 15:23 | 午夜寻欢
终于学习到怎么用自定义属性了!
可我还是不太明白你这些代码要完成的功能是什么?
难道就是简单的类型转换吗?
有这个必要写这么长的代码吗? 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 17:01 | Ariel Y.
我这段代码可以省去以后在页面里处理Query String的代码。
比如以前写:
public Guid userId;
public int count;
public void Page_Load()
{
try
{
userId = new Guid(Request.QueryString["UserId"].ToString());
}
catch
{
throw new Exception();
}
if(Request.QueryString["Count"] == null || Request.QueryString["Count"].ToSTring() = string.Empty)
{
count = 0;
}
else
{
try
{
count = Convert.ToInt32(Request.QueryString["Count"].ToString());
}
catch
{
throw new Exception();
}
}
}
现在只要写:
[HttpQueryString("UserId")]
public Guid userId; // 这里的字段不能是private的。
[HttpQueryString("Count", 0)]
public int count; // 这里的字段不能是private的。
就可以了。
难道你只看到了类型转换?
怎么说也是根据定义的变量的数据类型自动转换对应的QueryString吧?呵呵。
我觉得“有这个必要写这么长的代码吗?”这种思想是很有害的一种想法。
假设我这个代码有100行,我一次就写这么多了,以后每次就只有几行。如果不这么干(我是说,不提炼一些东西出来),你每页都要写,假设20行,你写一个项目我想也不仅仅只有5个页面吧?你看,做一个项目我就比你快:)
就像我开头说的,做一些枯燥重复的开发是没有意义的。永远是软件工人。
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 17:47 | lee_j
我看完楼主的代码后,发现从设计上有一个失误.PageBase类是实现代码复用的关键,而用自定义Atribute反而有画蛇添足的感觉.正如楼主所说利用反射机制令代码的效率降低.
我想有两种方法去改进
1.把PageBase的SetField功能移到HttpRequestStringAttribute类中;
2.不用自动义Attribute,改成Interface.PageBase去实现Interface,而不用反射机制.
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 22:35 | 木野狐
我认为这种实现方法过于麻烦。我的实现通常都是这样的:
在一个公共的方法类里面这样写,
public class Util {
private Util() {}
// 从 querystring 集合中安全的取得一个 string. (总是不会有 null,所以叫做 'Safe')
public static string GetStringSafeFromQueryString(Page page, string key) {
string value = page.Request.QueryString[key];
return (value == null) ? string.Empty : value;
}
// 在上述基础上,实现几个常用类型的获取方法。
public static int GetInt32SafeFromQueryString(Page page, string key, int defaultValue) {
string value = GetStringSafeFromQueryString(page, key);
int i = defaultValue;
try {
i = int.Parse(value);
} catch {}
return i;
}
// double 的实现
public static double GetDoubleSafeFromQueryString(Page page,
string key, double defaultValue) {
string value = GetStringSafeFromQueryString(page, key);
double d = defaultValue;
try {
d = double.Parse(value);
} catch {}
return d;
}
// 同理可以写出 float, ... 的实现
}
在我的任何页面里面,要获取 querystring 的时候,只要这样就可以了:
比如我要获取一个 string:
string name = Util.GetStringSafeFromQueryString(this, "name");
if (name.Length >0) {
// 进行正常的处理...
} else {
// 不处理。
}
获取 int:
int id = Util.GetInt32SafeFromQueryString(this, "id", 0);
处理 double, float 等等方法完全一样。
我认为就一个 QueryString 的处理没必要上升到反射的高度,其实有时候反过来想想,实现的那么复杂也许会丧失一定的灵活性。比如我某个值忽然要改为从 Form 里面得到呢?从 Session 得到呢?这时候就可以比较出哪种做法更适合敏捷的适应需求。
页面里的 QueryString 的处理,之所以大家都很痛恨手工写编码,无非是因为这么几点:
1. 需要判断是否 == null 才敢用 .ToString(), 很不爽。稍微不注意,就会抛出异常导致页面错误。
2. 整形,double 等值类型从 QueryString 里面获取的时候,不知道是否为合法的数值,因此 Parse 的时候总是要写重复的处理异常的代码。
归纳一下,其实,一个页面用下列语法获取一个 QueryString 的时候,他得到的是如下东西:
(假设用 string name = Request.QueryString["name"]; 来获取。)
1. ...test.aspx 得到 null
2. ...test.aspx?name= 得到 ""
3. ...test.aspx?name=abc 得到 "abc"
我认为 1 和 2 的情况实际上从程序处理上来讲,是没有区别的。因此判断 null 没有必要,我们每次都将 null 的值自动让他转为 string.Empty 应该是比较安全的做法。
基于上述理由,我觉得如我上面所写的简单的工具类,就可以轻量级的解决安全的读取 QueryString 的问题。
有不对的地方,请大家多多指教。 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-16 23:35 | 双鱼座
呵呵,这种方式与我从前做权限控制的方式几乎一样,用来处理QueryString的确小题大作了一点。两处缺陷:一是污染了Page类的代价太大了一点(自然木野孤的方案清洁一点);二是必须定义一个Field并且要加上自定义标签并且要与QueryString键字符串相吻合。
我在控制权限的时候,那个自定义标签是抽象的,加在Page固有的Field上(通常是页面中静态的Control),对于不同的Control根本不同的权限采取不同的策略进行不同的处理,具有充分的可扩充性,这样污染Page类就物有所值。 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-17 09:19 | Terrylee
楼主的设计思想很好……
可是为了QueryString花这么大的代价,值得吗? 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-17 10:12 | Ariel Y.
@各位
有人说这方法画蛇添足,有人说麻烦有,人说污染,有人说小题大做。我的想法呢,很简单,前边已经说过,我是为了少写代码,越少越好,呵呵。让机器多干点,人少干点,没错吧?其实,我也有个前提,做的一些项目都是小系统,在局域网内运行,一个站点跑一个Xeon的Server。我何苦折磨自己去讨好Xeon呢?麻烦?谁麻烦?我们麻烦还是机器麻烦?机器麻烦?干吗不麻烦它?几个G的脑瓜天天在那儿傻着!
对于Large-scale网站,我才不会用这个,性能即过程!
这么多高人关注,谢谢,呵呵。下边的言语如果多有得罪,还请见谅!
@lee_j
第一点,我和你想的一样,但是我不会,能指点一下吗?在Attribute里可以读到被它绑定的对象吗?我没找到方法。
第二点,没明白你的意思,Interface来做什么?但是好像对于我这篇文章就跑题了,我这篇文章叫一行代码搞定QueryString,呵呵。
请指教!
@木野狐
你这类代码的思想,正是我现在用的。不过我觉得完全没有必要传那个Page进去,用HttpContext.Current.Request.QueryString[]就可以读了
而且现在我有两种实现,一个是你这种Utility类,一种更OO的方法是自己实现一个QueryString类作为Page基类的成员,用的时候:this.QueryString.GetInt32(......);
@双鱼座
你的文章我很喜欢,但是先说一句得罪了!我有些出离愤怒了!
第一,怎么就叫代价大了?怎么就小了?
第二,必须定义一个Feild..............................。难道其他方式不用定义变量吗?其他方式不更是要写代码吗?其他方式不需要与QueryString键字符串相吻合吗?难道一行代码都不用写就让我实现吗?我可做不到:(
为什么你的污染就值?怎么污染就不值?太主观了吧?我地孩儿也是孩儿啊,555555。
@Terrylee &All
其实我这篇文章讨论的问题真是芝麻绿豆大点子的事儿,纯属是玩些技术把戏,我也就是写着玩儿玩儿。但是真的写好了,并且简单好用,何乐而不用呢?
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-17 10:27 | 木野狐
楼主的出发点很好,从技术的角度讲也是一种很有益的练习,不过双鱼座所说的“污染”其实只是从 OO 思想的角度来讲的,并没有任何贬低的意思啊。还望楼主不要误解了。常常我们会说“污染”一个名称空间之类的说法,其实说的不过是某个类,或者某个名称空间下干了比它应有的职责更多的事情而已,呵呵。
关于我的回复,昨天回复完后,也贴到自己的 blog 上去了:
http://rchen.cnblogs.com/archive/2006/01/16/318561.html
根据 stone790809 网友的建议,我现在已经改进了做法,不再传递 Page 类作为参数了,这个跟你的建议是一致的 :)
其实并非我不知道 HttpContext.Current.Request 这个用法,只是平常传递 Page 对象传惯了,写成了惯性而已,呵呵。
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-17 10:40 | Ariel Y.
@木野狐
哦,才发现,确实,从OO的角度讲,确实有污染,谢谢指正!
@双鱼座
不好意思啦。 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-17 17:13 | zkxp
什么是OO到处看到,汗一个先。。。 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-17 22:55 | sema
国外有类似思路的文章介绍,大家可以参考一下
http://www.codeproject.com/aspnet/WebParameter.asp
如果英文的看着累,也可以看看翻译的文章
http://dragon.cnblogs.com/archive/2005/03/24/125160.html
应该说这种思路还是很有意思的。但是实际对效率的影响的确需要评估。
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-18 00:22 | Ariel Y.
@sema
您的名字让我想起一句广告:“穿什么,就是什么”:)
楼上吓我一身汗,跟我的好像!我可是干巴巴想出来的,呵呵。
不过我喜欢这种说法:“但是实际对效率的影响的确需要评估”,而不是有些人(没有特指,请勿对号入座,真的):“效率很差,效率不高”。
知道读数据DataReader比DataAdpater+DataSet快多少吗?总有人说快好多,实际的评测结果好像是14%-18%(参考自“DEV411 ASP.NET: Best Practices For Performance - Stephen Walther www.SuperexpertTraining.com - TechEd 2004”)
@zhxp
OO means Object-Oriented Programming Concepts
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-19 12:35 | torome
看了高人的文章.
自己感觉还有很多要学习。.
努力!~ 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-20 15:10 | Stanley Liu
搞明白自定义属性了,happying
谢谢Ariel Y. ~ 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-01-23 08:59 | xiao_p
能不能把鼠标特殊效果撤销掉了……
实在是难受,看得时候……
呵呵
对于文章,就没有什么好说的了,确实不错~~
回复
# re: 一行代码搞定你的QueryString!(原创) 2006-02-14 10:00 | chating
是个好方法,但程序代码效率低. 回复
# re: 一行代码搞定你的QueryString!(原创) 2006-04-21 08:13 | 生活被我强奸。。。
呵呵。。这么一大堆我不太明白@我来这里是谢谢你的:)。。
回复
# re: 一行代码搞定你的QueryString!(原创)2006-04-21 14:33 | Ariel Y.
谢谢。 回复
Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=1368460
本文转自
http://blog.youkuaiyun.com/jelink/archive/2006/11/05/1368460.aspx