如何将字符串动态转换为指定的值类型
来源:互联网 发布:java反射获取注解 编辑:程序博客网 时间:2024/05/16 00:26
作者:eaglet
转载请保留原作者署名并注明出处。
我们日常工作中经常会遇到将字符串转换为值类型的问题,比如"123"转换为一个Int32类型,这个很简单,我们只要调用int.Parse 函数就可以实现。eaglet今天要说的是,一些应用中往往在编码阶段无法知道字符串需要转换成的值类型的具体类型,而需要在运行时动态指定类型进行转换,遇到这种问题,我们如何解决?
一个典型的例子。
如下函数,我们只知道value是一个基本值类型,比如(System.Int32, System.Int16, System.Double 等等)或者是一个字符串类型。但我们无法在编码时确定这个value具体是什么类型,它可能是由一个外部组件从某个数据源中读出来的基本类型中的一种类型的实例或者是字符串类型实例。
这个函数希望实现比较value 是否在minValue, maxValue这两个字符串对应的数值区间类,其中minValue 和 maxValue 构成一个闭区间,即
value in [minValue, maxValue]
public static bool MyComparer(object value, string minValue, string maxValue)
要解决这个问题,我们需要解决两个基本问题。
1. 如何比较value 和 minValue, maxValue
2. 如何将minValue 和 maxValue 转换到value 对应的数据类型
首先我们来看如何进行比较
所有的基本值类型和string 类型都实现 IComparable这个接口。我们可以指定 value 为IComparable,然后调用CompareTo来进行比较。不过这里有个问题,CompareTo 函数的参数obj 虽然是一个 object类型,但这个 obj 的类型必须和 value 一致,否则将发生异常。也就是说我们不能把minValue 任意转换成某个类型比如 long带进去,而需要将 minValue 和 maxValue 转换成和 value 一样的类型才行。
下面我们就来讨论如何将字符串转换为指定的值类型。
我们需要实现下面的函数:
public static object ToType(Type type, string value)
type 为指定的类型,value 为输入的字符串。
首先我们知道所有的基本值类型都有一个叫 Parse 静态函数,我们只要把这个静态函数反射出来,就可以通过这个静态函数将字符串转换成对应的值类型。
下面代码给出如何反射出这个静态函数。通过向对象type(Type类型)的GetMethods 函数输入 BindingFlags.Static
| BindingFlags.Public 参数,我们可以枚举出这个类型所有的静态公共函数。
然后我们判断这个函数的名称是否为 "Parse" ,由于 Parse 函数有多个重载,但一个参数的重载只有 Parse (String)
所以我们需要判断mi 只有一个参数,这时取到的 mi 就是 Parse (String) 函数。
foreach (MethodInfo mi in type.GetMethods(BindingFlags.Static
| BindingFlags.Public))
{
if (mi.Name == "Parse" && mi.GetParameters().Length == 1)
{
parseMethod = mi;
break;
}
}
接下来就是如何调用这个函数来转换字符串了。
如下面代码,我们调用MethodInfo 的 Invoke 方法来动态调用这个函数,由于是静态函数,第一个参数 obj 传入null. 并在第二个参数中带入value 这个参数。
下面给出字符串转换为指定类型的完整代码
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace Eagelt.Convert
{
public class ConvertString
{
public static object ToType(Type type, string value)
{
if (type == typeof(string))
{
return value;
}
MethodInfo parseMethod = null;
foreach (MethodInfo mi in type.GetMethods(BindingFlags.Static
| BindingFlags.Public))
{
if (mi.Name == "Parse" && mi.GetParameters().Length == 1)
{
parseMethod = mi;
break;
}
}
if (parseMethod == null)
{
throw new ArgumentException(string.Format(
"Type: {0} has not Parse static method!", type));
}
return parseMethod.Invoke(null, new object[] { value });
}
}
}
下面这个是根据"流言社"的评论改进的。谢谢"流言社"!
{
public static object ToType(Type type, string value)
{
return System.ComponentModel.TypeDescriptor.GetConverter(type).ConvertFrom(value);
}
}
MyComparer 函数的完整代码
{
IComparable comparableObj = value as IComparable;
object min;
object max;
if (comparableObj == null)
{
throw new ArgumentException(string.Format(
"Type: {0} does not inherit from IComparable", value.GetType()));
}
min = ConvertString.ToType(value.GetType(), minValue);
max = ConvertString.ToType(value.GetType(), maxValue);
return comparableObj.CompareTo(min) >= 0 && comparableObj.CompareTo(max) <= 0;
}
测试代码
Console.WriteLine(MyComparer(3, "1", "2"));
Console.WriteLine(MyComparer((byte)2, "1", "3"));
Console.WriteLine(MyComparer((double)3, "1", "2"));
Console.WriteLine(MyComparer("3", "1", "2"));
测试结果
True
False
True
False
False
最后提一个简单的问题,供大家思考,如果我们需要将字符串转换成我们自己定义的复杂类型,如何实现呢?
比如我们有一个结构
struct UInt128
{
public ulong Low;
public ulong High;
}
我们将这个结构的实例对象传入到函数
Console.WriteLine(MyComparer((UInt128)2, "1", "3"));
这样可以吗?怎样做才能做到呢?
- 如何将字符串动态转换为指定的值类型
- 动态的将字符串转换为指定的类型
- C#将指定字符串转换为枚举类型对应的值
- freemarker将指定日期字符串转换为指定的格式
- 如何将16进制字符串转换为Int32类型
- 29、Java中如何将字符串转换为日期类型?
- Groovy将字符串类型转换为自定义类型的方法
- 将字符串类型的数组转换为数组类型数组
- 将一个浮点数,转换为指定格式的字符串
- java中日期时间格式与毫秒数的转换如何将指定时间转换为Date类型
- 将字符串转换为日期,将日期转换成指定格式的字符串
- 高效的将整型类型转换为字符串的方法
- 如何把FOXPRO的日期类型转换为字符串类型!
- 将xml类型的字符串转换为hashmap
- SQLSERVER数据库将数值类型转换为字符串的问题
- 函数---将十六位的网络地址转换为字符串类型
- 将字符串转换为枚举类型
- 将数字类型转换为字符串
- vc6开发activex并发布全攻略(二)(初级篇)
- 变换的立体感表格
- 有道难题之OO
- 有道难题第一题 在徐少侠的算法基础上改进
- J2EE 的四层模型
- 如何将字符串动态转换为指定的值类型
- 只允许运行一个实例的程序(互斥程序)
- Hubble.net V0.3 版本正式生成
- WinForm 下实现一个自动关闭的MessageBox
- Short Guide to install Oracle 10 on Linux
- 一个简单的SQL 行列转换
- Hubble.net 值得纪念的一天
- 二进制文件和文本文件到底有什么区别
- 盘古分词--功能简介