Yok

苦海无涯,回头是岸啊

利用反射实现ASP.NET控件和数据实体之间的双向绑定,并且在客户端自动验证输入的内容是否合法

首先请原谅我蹩脚的中文...玩电脑太多都不太会说话了,但愿大家看的明白

ASP.NET的UI不像做Winform那么容易,设个DataSource和DataField就什么都搞定了.虽然提供了<%#%>这样形式的绑定,但是这种绑定是单向的,只能从数据源赋值给控件,无法把控件的内容写回数据源.所以,在保存数据时得一条一条写,还得处理null,类型转换什么的.例如
anObject.AnIntProperty =  Convert.ToInt32(aControl.Text == "" ? aControl.Text  : "0"); //用数据实体的话
或者
aDatarow["AnIntField"] =  Convert.ToInt32(aControl.Text == "" ? aControl.Text  : "0"); //用datarow的话
有时一张表单几十个字段,这样写准会疯的 >_<

于是我利用反射做了一个东西,实现了让控件显示数据实体(我惯用o-r mapping而不是DataSet/DataRow,当然DataRow也能用类似的方式去搞)的内容和把控件的内容赋回给数据实体,然后,顺便把数据合法性验证也做进去了(反射性能损耗大,不干多点东西心里不平衡啊)

在我的BindingManager类中约定,凡是"_"结尾的控件将会被处理,这些控件会和实体类相对应的属性自动关联起来.通过设置PrefixLength的值指定从控件名的第几个字符开始匹配实体类属性,例如我习惯用3个字符做控件前缀,于是设PrefixLength为3,和Name属性关联的控件名就形如txtName_.然后调用GetEntityValues(Page,theObject)和SetEntityValue(Page,theObject)来实现控件和数据实体之间的绑定.

至于"顺便"做的合法性验证的功能,首先确保了控件输入的内容符合实体属性的类型,这是自动完成的,例如一个int属性对应的控件不能填写字母.如果有更多的要求,例如用正则表达式,不允许空值,或者在出错时给用户更详细的提示,则给实体的属性加上ValidateAttribute后就可以实现.

这是一个我写的Demo的其中一部分:Person类,其中有各种不同类型的属性.可以看到ValidateAttribute指定了Name不可空,描述为"姓名",这样,当 txtName_.Text 是空值时提交数据,将会弹出提示"姓名不能为空".而Id则规定了要输入现在新身份证的格式,如果不符合的话则提示"身份证号码格式不正确".另外,Sex是个自定义的类.得做个针对他的TypeConverter,然后给Sex类加上TypeConverterAttribute才可能被正确的处理.


    public class Person
    
{
        
public Person()
        
{
                
        }


        
string _name;
        
decimal _height;
        DateTime _birthday;
        Sex _sex;
        [Validate(AllowNull 
= false, Description = "姓名")]
        
public string Name 
        
{
            
get {return _name;}
            
set {_name = value;}
        }

        [Validate(Description 
= "身高")]
        
public decimal Height
        
{
            
get {return _height;}
            
set {_height = value;}
        }

        
string _id;
        [Validate(RegEx 
= "^\\d{17}(\\d|x)$", Description = "身份证号码")]
        
public string Id 
        
{
            
get {return _id;}
            
set {_id = value;}
        }

            
            
public DateTime Birthday
        
{
            
get {return _birthday;}
            
set {_birthday = value;}
        }


        
public Sex Sex 
        
{
            
get {return _sex;}
            
set {_sex = value;}
        }

    }

在使用Person类时,一行语句就能实现控件和数据间赋值.以下是一个aspx后台代码的片断:

        Person p 
= new Person();
        BindingManager bm 
= new BindingManager();
        
private void Page_Load(object sender, System.EventArgs e)
        
{

            
if (!IsPostBack) 
            
{
                
//validateForm()是客户端验证控件合法性时调用的函数                       
                Button1.Attributes["onclick"= "return validateForm();"
                
//给p随便设点值
                p.Name = "Yok";
                p.Height 
= 170;
                p.Sex 
= Sex.Male;
                p.Birthday 
= new DateTime(19801121);
                
//这样就可以让控件显示p的内容                
                bm.GetEntityValues(Page, p);
            }

        }


        
private void Button1_Click(object sender, System.EventArgs e)
        
{
            
//把值赋给实体
            bm.SetEntityValues(Page, p);
            
//这时p已经从控件获得各个属性的值.Write出来看一下是否正确
            Response.Write("Name = " + p.Name + "<br>");
            Response.Write(
"Height = " + p.Height + "<br>");
            Response.Write(
"Birthday = " + p.Birthday.ToShortDateString() + "<br>");
            Response.Write(
"Id = " + p.Id + "<br>");
            Response.Write(
"Sex = " + p.Sex.ToString() + "<br>");
        }



不说了,我的代码应该比我的文字好懂

posted on 2004-11-23 22:24 Yok 阅读(3506) 评论(29)  编辑 收藏 网摘

评论

#1楼 2004-11-24 08:34 Ninputer[未注册用户]

怎么都喜欢压成RAR?
虽然安装盗版的WinRAR对大部分人来说并不是特别过意不去,但是偶尔就会有买不起但坚持原则的人解不开你的文件……
  回复  引用    

#2楼[楼主] 2004-11-24 08:43 Yok      

那是不是应该做成自解压的exe -_-   回复  引用  查看    

#3楼[楼主] 2004-11-24 08:47 Yok      

买不起的话...好像只是每次打开时弹个注册提示吧?还能用的   回复  引用  查看    

#4楼 2004-11-24 08:53 Ninputer[未注册用户]

拜托,你用RAR压成Zip也好啊,我现在想看。谢啦!   回复  引用    

#5楼[楼主] 2004-11-24 09:01 Yok      

哦...这就去改 -_-   回复  引用  查看    

#6楼[楼主] 2004-11-24 09:09 Yok      

改成exe了
如果谁又跳出来说我在linux下啊...把url的exe改成zip吧,已经多准备一份了 -_-
  回复  引用  查看    

#7楼 2004-11-27 19:08 Mocety

只是绑定而已,但就用了反射,在这里就有性能损失就得不偿失了。ORM在数据层用就好,千万不要滥用。如果能提高性能,我宁愿多花点时间去敲代码了。还有就是客户端验证,安全性不够好。   回复  引用    

#8楼[楼主] 2004-11-27 23:40 Yok      

性能的问题就见仁见智了,这样做耗的时间比直接赋值多10倍,不过赋值操作的时间在整个程序执行过程只占很小比例,整体来说不会损失太大.
DataGrid绑定到数据实体是用反射,DataBinder.Eval也是用反射,我觉得没什么好担心的
  回复  引用  查看    

#9楼[楼主] 2004-11-27 23:45 Yok      

还有就是客户端验证,安全性不够好
==========================
为什么呀?
  回复  引用  查看    

#10楼[楼主] 2004-11-29 10:11 Yok      

经测试,一个DataReader根据主键从数据库读取一条记录并用BindingManager去绑定的页面,比直接赋值慢了15%左右。这15%对我现在做的项目来说是值得的,表单的字段多的离谱。人手不够(我一个人)而且时间紧迫,而且这网站的负荷会很低(有形象工程之嫌),可能一天也只是处理几条数据   回复  引用  查看    

#11楼 2004-11-30 03:09 Pogey

客户端验证的好处是响应速度好,可是安全性确实不妥,有些人就是不用IE的

至于ORM嘛,业务逻辑层如果不是很复杂的,就不用好了,我公司就约定了,业务逻辑不太复杂,数据库表关系不多的,一律用ADO.NET。而对付大企的,关键部分使用ORM。其实很多朋友都说,不复杂任务ORM反而慢,而且现在ORM在.net的应用不如Java,性能确实不好(最惨是客户反馈说有点慢!)。现在出了很多第三方ORM组件,但信心都不足。我觉得在大任务里面结合ORM和ADO.NET是比较好的。现在是乱世时期,对ORM过热可能不太好
  回复  引用    

#12楼[楼主] 2004-12-01 17:07 Yok      

.net的ORM确实不成熟,但是我认为有前途,毕竟在java的应用是很成功的.所以我们也不应逃避,风险不大的前提下可以尝试一下,算是为推动.net的发展做点贡献吧~   回复  引用  查看    

#13楼 2005-06-24 16:08 山坡上的男孩      

Orm 在将来所谓对象数据库流行起来后,也许就消失了,:)呵呵。
不过,现在很多系统的开发,其实还是要看实际需求,要在很多矛盾中作出平衡。
软件开发工程也是是矛盾无所不在的一门科学啊,还是要遵循毛主席的矛盾指导原则,抓住主要矛盾,具体情况具体分析。不过具体分析的前提是要对事务的本质要了解,所以,还是要多看看,多了解,这个是基础。
  回复  引用  查看    

#14楼 2005-07-28 16:02 zhihorse[未注册用户]

Yok,你好!

http://www.foshan.com.cn/production/binding.exe
不能下载,是否能提供其他的下载地址!

谢谢! z_zhi@163.com
  回复  引用    

#15楼 2005-09-09 09:24 ericfish[未注册用户]

已经收到你发的新版代码,再次感谢   回复  引用    

#16楼 2005-10-09 21:55 Yatoel[未注册用户]

确实无法下载,是不是iis的安全性设置不能下载exe文件的,能不能发给我一份,谢谢

hu_tiger@163.com
  回复  引用    

#17楼 2005-11-03 16:36 浪子      

一样得不到代码.
dayich@hotmail.com

谢谢.

直接传到cnblogs是否更好.
  回复  引用  查看    

#18楼 2005-11-03 17:25 川仔      

一样得不到代码.
chuanzai@msn.com

谢谢.

直接传到cnblogs是否更好.
  回复  引用  查看    

#19楼 2005-11-04 08:47 飞影[未注册用户]

发我一份,好吗,下不了呀.
bmiracle@126.com

谢谢 ~~
  回复  引用    

#20楼 2005-11-04 10:38 freedomkavin[未注册用户]

谢谢,也发给我一份吧
freedomkavin@gmail.com
  回复  引用    

#21楼 2005-11-05 12:59 无名      

也给我发一份,你这个真值得学习
非常感谢
shiningrise@163.com
  回复  引用  查看    

#22楼 2005-12-14 13:33 small[未注册用户]

我而已要 smallmage@126.com 谢谢了   回复  引用    

#23楼 2005-12-15 10:55 w_pz@163.com[未注册用户]

思路不错,这样是减少了很多的工作量。
程序员是越懒越香
在你的自定义属性里面最好能再加个显示开关,可能会更好一些。

w_pz@163.com
  回复  引用    

#24楼 2006-09-25 13:31 gavin[匿名][未注册用户]

pignut_wang@126.com

下载不到代码,能否发一份给我?谢谢!
  回复  引用    

#25楼 2007-09-16 17:49 阿慧南      

楼主提供了很好的方法,不知道页面数据结构比较复杂时(比人对应几个不同的对象时),效率等是否会有影响。

之前一个项目中大量用到数字输入的文本框,对于采用传统的页面验证或者ASP.NE验证控件,工作量都是盛大。
而在取数字文本取值时必须先检验是否填写等等。

所以自己写了一个笑小控件集
http://www.cnblogs.com/MicroSystem/archive/2007/08/09/739241.html" target="_new">http://www.cnblogs.com/MicroSystem/archive/2007/08/09/739241.html

zhe
  回复  引用  查看    

#26楼 2009-01-15 12:41 wwzwcy[未注册用户]

非常感谢呀   回复  引用    

#27楼 2009-04-21 16:30 Sunshushou      

刚刚下载了,发现代码不全,BindingManager这个类在哪里呀?   回复  引用  查看    

#28楼 2009-05-15 16:34 judeangle

能发份代码给我不?谢谢。 judeangle@163.com   回复  引用    

#29楼 2009-06-08 13:31 老李飞刀      

求最新代码, 本贴提供下载的代码好像不是完整的!

5241307@qq.com
  回复  引用  查看    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 67753




相关文章:

相关链接:

<2009年7月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

导航

统计

公告

不玩了不玩了不玩了不玩了不玩了不玩了不玩了不玩了

与我联系

搜索

 

常用链接

留言簿

我参与的团队

我的标签

随笔分类

随笔档案

相册

Friend Links

积分与排名

最新评论

阅读排行榜

评论排行榜