WinForm TextBox自定义扩展方法数据验证
本文转载:http://www.cnblogs.com/gis-crazy/archive/2013/03/17/2964132.html
查看公司项目代码时,存在这样一个问题:winform界面上有很多信息填写,提交后台服务器更新,但数据的合法验证及值的转换却不太敢恭维,一堆的if判断和转换,便想着是否能扩展个方法出来,琢磨出个思路,记录下来与大家共同探讨,有不对的地方还请大家指正。
设计思路:
1. 由于大部分从TextBox控件中获取数据值,可以扩展个泛型方法出来,直接根据转换后的数据类型获得值,类似这样,
var value = this.txtSample.GetValue<int>();
2. 可以传入一个委托用来处理转换失败的操作,并重载此方法,提供一个默认的操作。
好,下面开工:
1. 创建TextBox类型的扩展方法
引用MSDN的解释:扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。 对于用 C# 和 Visual Basic 编写的客户端代码,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异。
扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为前缀。 仅当您使用using 指令将命名空间显式导入到源代码中之后,扩展方法才位于范围中。
注意:扩展方法是在非嵌套、非泛型静态类内部定义的
2. 由于转换类型未知,但为值类型,故采用泛型方法设计,并加上strut泛型约束,由于允许自定义处理转换失败时的操作,故传入一个Action委托来实现,如下:

public static TResult GetValue<TResult>(this TextBox textBox, Action<TextBox> failed)
where TResult : struct
{
var type = typeof(TResult);
var method = type.GetMethod("TryParse", new Type[] { typeof(string), type.MakeByRefType() });
var parameters = new object[] { textBox.Text, default(TResult) }; // 若转换失败,执行failed
if (!(bool)method.Invoke(null, parameters))
{
failed(textBox);
throw new InvalidCastException("输入值格式不正确,请检查输入值。");
} return (TResult)parameters[1];
}

这里采用反射机制来调用类型的T.TryParse(string param, out T value),例如Int32.TryParse(string param,out Int32 value)等,需要注意的是:
(1). GetMethod()方法,必须传入合适的参数(要反射的方法的签名)来确定方法唯一,例如碰到重载这种情况(比较常见),否则返回值为null,方法的签名中,若参数带有ref 或out 关键字,则Type类型需要加上.MakeByRefType(),如上。
(2). 得到唯一的方法实例后,可以传入相应的参数,调用Invoke方法来实现方法的调用,MethodInfo.Invoke(object obj, object[] parameters)方法第一个参数为反射调用该方法的对象,如果为静态方法(比如本例),可以传入null,第二个参数为方法的参数,顺序必须与方法签名一致。
(3). 方法参数中带有ref和out关键字,获得该值通过参数数组来获得。如本例中:parameters[1]
3. 定义转换失败操作的委托
C#内置封装的委托有两种,Action和Func委托,并有很多的重载版本,参数可以有十多个,所以不用担心参数问题。其中Action委托无返回值,属于Void类型,Func委托具有返回值,如Func<T,TResult>,在Linq操作中比较常见,在该例中,无返回值的必要,故采用Action委托,由于需要处理转换失败的操作,故将TextBox作为该委托的参数里进行处理,如代码所示,当转换失败时进行处理:
// 若转换失败,执行failed
if (!(bool)method.Invoke(null, parameters))
failed(textBox);
在此简单介绍下委托:委托其实是一个类型,通过反编译工具可以看出来,当构造委托时传入一个方法,其实会隐形的传入两个参数(target,methodPtr),target参数为调用该方法的实例,若静态方法,则为null,methodPtr为传入方法的内存地址(在元数据中存贮该信息),faild(textBox)表面看不太好理解,为什么一个对象后面带一个参数,其实C#编译器为我们做了很多工作,在这里实质为faild.Invoke(textBox),这样看还好理解委托是个类型,通过faild的委托对象来调用该委托所注册的方法。
4. 创建重载版本:
用lambda表达式定义默认的转换失败操作,如果转换失败,则提示信息,并全部选中和定位到该输入框上。

public static TResult GetValue<TResult>(this TextBox textBox, bool isShowError)
where TResult : struct
{
return GetValue<TResult>(textBox, p =>
{
if (isShowError)
{
p.Focus();
p.SelectAll();
MessageBox.Show("输入值格式不正确,请重新输入!",
"提示--值类型:" + typeof(TResult).Name,
MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
});
}


///默认版本,调用上个重载方法
public static TResult GetValue<TResult>(this TextBox textBox)
where TResult : struct
{
return GetValue<TResult>(textBox, true);
}

5. 实验测试:
新建winform程序,界面如图所示:
后台代码:

private void btnConvert_Click(object sender, EventArgs e)
{
try
{
var intValue = txtInt.GetValue<int>();
var floatValue = txtFloat.GetValue<float>();
var dateTimeValue = txtDateTime.GetValue<DateTime>();
var doubleValue = txtDouble.GetValue<double>();
}
catch (Exception) { }
}

如果输入值非法,则提示错误,如图所示:
转载请注明出处:http://www.cnblogs.com/gis-crazy/archive/2013/03/17/2964132.html
WinForm TextBox自定义扩展方法数据验证的更多相关文章
- Silverlight实例教程 - 自定义扩展Validation类,验证框架的总结和建议(转载)
Silverlight 4 Validation验证实例系列 Silverlight实例教程 - Validation数据验证开篇 Silverlight实例教程 - Validation数据验证基础 ...
- AbpVnext使用分布式IDistributedCache Redis缓存(自定义扩展方法)
AbpVnext使用分布式IDistributedCache缓存from Redis(带自定义扩展方法) 我的依赖包的主要版本以及Redis依赖如下 1:添加依赖 <PackageReferen ...
- Jquery自定义扩展方法(二)--HTML日历控件
一.概述 研究了上节的Jquery自定义扩展方法,自己一直想做用jquery写一个小的插件,工作中也用到了用JQuery的日历插件,自己琢磨着去造个轮子--HTML5手机网页日历控件,废话不多说,先看 ...
- Layui数据表格加入自定义扩展方法(重新渲染Render当前页数据)
具体开发中遇到的问题如下, 数据表格的重新渲染或重新加载会导致当前操作的分页 或 配置被清空.我正在操作第5页,重新渲染后就回到了最原始第1页. 需要达到的效果是: 不调用接口,仅仅只是从table. ...
- Jquery自定义扩展方法(一)
jquery是一款流行的JS框架,自定义JS方法,封装到Jquery中,调用起来也挺方便的,怎么写Jquery扩展方法那,网上翻阅了一部分代码,其实也挺简单的: 方式一: (jQuery.fn.set ...
- Unity中自定义扩展方法
问题背景 在使用unity开发过程中,通常会遇到一种情况,比如说给物体重新赋值坐标的问题, Transfrom tran: ,pos_y=,pos_z=; tran.position=new Vect ...
- C# 实现和调用自定义扩展方法
定义和调用扩展方法 定义一个静态类以包含扩展方法.该类必须对客户端代码可见. 将该扩展方法实现为静态方法,并使其至少具有与包含类相同的可见性. 该方法的第一个参数指定方法所操作的类型:该参数必须以 t ...
- Swift学习(二):自定义扩展方法(Extensions)
扩展就是向一个已有的类.结构体或枚举类型添加新功能(functionality) 扩展可以 添加计算型属性和计算静态属性 定义实例方法和类型方法 提供新的构造器 定义下标 定义和使用新的嵌套类型 使一 ...
- MVC———用自定义扩展类实现验证
废话少说,直接上图 →_→ NO.1 NO.2 NO.3 NO.4 NO.5 NO.6 NO.7 NO.8 NO.9 NO.10 NO.11 NO.12 NO.13 NO.14 NO.15 NO.16 ...
随机推荐
- 用Eclipse 开发Dynamic Web Project应用程序 【转】
简介:本文仅简单介绍基于Eclipse开发Dynamic Web Project应用下的JSP,Servlet及TOMCAT数据源的配置和开发. 软件环境: Eclipse Java EE IDE f ...
- NS实现采用的技术大多是PHP,如果采用java、 .net是否同样适用?
SNS采用的技术可不都是PHP (不局限于国内),特别是国外的新兴公司,基本上没有再用PHP的了,国内到还是蛮常用的.简单说说我知道的几个案例:Facebook (PHP):Facebook采用PHP ...
- String的一些细节
String 常量池问题 (1) 字符串常量的"+"号连接,在编译期字符串常量的值就确定下来, 拿"a" + 1来说,编译器优化后在class中就已经是a1. ...
- AD RMS Bulk Protection Tool 批量加密解密office文档
1.Active Directory Rights Management Services Bulk Protection Tool http://www.microsoft.com/zh-cn/d ...
- hdu 4433
一道dp题,虽然知道是dp,但是不会做: 学习了ACM_cxlove大神的代码,终于明白了: 搬运工: dp[i][j][k]表示 前i个已经完全匹配,而这时候,第i+1个已经加了j位,第i+2位已经 ...
- 基于Spring Boot构建的Spring MVC快速入门
原文地址:http://tianmaying.com/tutorial/spring-mvc-quickstart 环境准备 一个称手的文本编辑器(例如Vim.Emacs.Sublime Text)或 ...
- VS2005 检测内存泄漏的方法(转载)
一.非MFC程序可以用以下方法检测内存泄露: 1.程序开始包含如下定义: #ifdef _DEBUG #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __F ...
- java.math.BigInteger使用心得总结(转)
今天参考课本写了一个关于二进制与十进制转换的程序,程序算法不难,但写完后测试发现不论是二转十还是十转二,对于大于21亿即超过整数范围的数不能很好的转换.都会变成0.参考书籍发现使用使用BigInteg ...
- Discuz! x 2.5-3.0 beta 存储型跨站漏洞
漏洞版本: Discuz x 2.5 - 3.0 漏洞描述: Discuz! 已拥有11年以上的应用历史和200多万网站用户案例 是全球成熟度最高.覆盖率最大的论坛软件系统之一,淘帖处发表评论,直接插 ...
- JS 利用数组拼接html字符串
var cc = []; cc.push('<td colspan=' + fields.length + ' style="padding:10px 5px;border:0;&qu ...