C# TextBox 扩展方法数据验证详细说明
发布时间:2022-05-07 14:21:36
查看公司项目代码时,存在这样一个问题: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) { }
}
如果输入值非法,则提示错误,如图所示:


猜你喜欢
- 问题描述我在接受 mq 消息的时候,需要做一个重试次数限制,如果超过 maxNum 就发邮件告警,不再重试。所以我需要对 consumer
- 本文实例讲述了Hibernate环境搭建与配置方法。分享给大家供大家参考,具体如下:1.下载hibernate jar包:hibernate
- 本文实例汇总了Java的System.getProperty()方法获取信息的用法。分享给大家供大家参考。具体如下:System.out.p
- 本文实例讲述了Android6.0开发中屏幕旋转原理与流程。分享给大家供大家参考,具体如下:从Android 系统开发开始,这里写下Andr
- 一、场景Android项目的开发过程中,我们项目中的gradle的dependencies闭包中会引入很多三方依赖库,引入的库越多,越容易产
- 序初涉江湖,还望海涵!写点东西,纯粹是因为个人的记忆能力较弱,写些笔记罢了,若有错误还望雅正!对Android中的时间获取做个记录,以下为结
- 本文实例讲述了C#中委托用法。分享给大家供大家参考。具体分析如下:这里演示了如何使用匿名委托来计算员工的薪水奖金。使用匿名委托简化了程序,因
- 最近完成的差不多的项目突然需要加退款的流程需求了,所以来小小的实现以下。其实对比其他的支付和退款来说,支付宝算是特别专业,也是特别简单的一个
- 本文实例为大家分享了Unity3d简易五子棋源码,供大家参考,具体内容如下Unity3d部分对C#源码进行了改写简化:using Unity
- 本例子演示如何添加一个简单的单页导航,在此基础上,再演示如何在第2个页面中显示第1个页面中拨打过的所有电话号码。(1)通过该例子理解Andr
- 前言spring中解析元素最重要的一个对象应该就属于 BeanDefinition了;这个Spring容器中最基本的内部数据结构;它让xml
- 前言身在孤岛有很多无奈,比如说程序员属于比较偏门的职业。尤其是早些年,在行业里跳过几次槽后,可能你就已经认识整个圈子的人了。然后,再跳槽很可
- 今天介绍一个自己做的快递单号查询的简单APP,供大家参考。由于需要使用http和json,本文在build.gradle(module:ap
- 环境配置:Jdk1.8 + Tomcat8.5 + mysql + Eclispe(IntelliJ IDEA,Eclispe,MyEcli
- 1. 使用ApplicationEventPublisher 发布事件复制下面全部代码,右键包名,粘贴即可生成java类,执行即可看到效果。
- Android静默安装的方法,静默安装就是绕过安装程序时的提示窗口,直接在后台安装。注意:静默安装的前提是设备有ROOT权限。代码如下:/*
- 本文实例为大家分享了Android自定义EditText实现登录界面的具体代码,供大家参考,具体内容如下先看效果图:自定义edittext
- 本文实例为大家分享了TextView绘制背景的方法,供大家参考,具体内容如下效果:实现流程:1.初始化:对画笔进行设置mPaintIn =
- java读写ini文件、FileOutputStream在上课让学生练习文件读写,就让他们做了一个使用文件保存账号和密码的练习,有一个比较爱
- 目录第一点——加载网页结构第二点——解析网页结构,转变为符合需求的数据实体第三点——保存数据实体,转变为符合需求的数据实体第四点——main