先看一个字符串动态转换的典型例子 如下函数我们只知道value 是一个基本值类型比如(SystemInt SystemInt SystemDouble 等等) 或者是一个字符串类型但我们无法在编码时确定这个value 具体是什么类型它可能是由一个外部组件从某个数据源中读出来的基本类型中的一种类型的实例或者是字符串类型实例 这个函数希望实现比较value 是否在minValue maxValue这两个字符串对应的数值区间类其中minValue 和 maxValue 构成一个闭区间即 value in [minValue maxValue] public static bool MyComparer(object value string minValue string maxValue) 要解决这个问题我们需要解决两个基本问题 如何比较value 和 minValue maxValue 如何将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 函数输入 BindingFlagsStatic | BindingFlagsPublic 参数我们可以枚举出这个类型所有的静态公共函数 然后我们判断这个函数的名称是否为 Parse 由于 Parse 函数有多个重载但一个参数的重载只有 Parse (String) 所以我们需要判断mi 只有一个参数这时取到的 mi 就是 Parse (String) 函数 MethodInfo parseMethod = null; foreach (MethodInfo mi in typeGetMethods(BindingFlagsStatic | BindingFlagsPublic)) { if (miName == Parse && miGetParameters()Length == ) { parseMethod = mi; break; } } 接下来就是如何调用这个函数来动态转换字符串了 如下面代码我们调用MethodInfo 的 Invoke 方法来动态调用这个函数由于是静态函数第一个参数 obj 传入null 并在第二个参数中带入value 这个参数 parseMethodInvoke(null new object[] { value }); 下面给出字符串动态转换为指定类型的完整代码 using System; using SystemCollectionsGeneric; using SystemText; using SystemReflection; namespace EageltConvert { public class ConvertString { public static object ToType(Type type string value) { if (type == typeof(string)) { return value; } MethodInfo parseMethod = null; foreach (MethodInfo mi in typeGetMethods(BindingFlagsStatic | BindingFlagsPublic)) { if (miName == Parse && miGetParameters()Length == ) { parseMethod = mi; break; } } if (parseMethod == null) { throw new ArgumentException(stringFormat( Type: {} has not Parse static method! type)); } return parseMethodInvoke(null new object[] { value }); } } } MyComparer 函数的完整代码 public static bool MyComparer(object value string minValue string maxValue) { IComparable comparableObj = value as IComparable; object min; object max; if (comparableObj == null) { throw new ArgumentException(stringFormat( Type: {} does not inherit from IComparable valueGetType())); } min = ConvertStringToType(valueGetType() minValue); max = ConvertStringToType(valueGetType() maxValue); return comparableObjCompareTo(min) >= && comparableObjCompareTo(max) <= ; 测试代码 ConsoleWriteLine(MyComparer( )); ConsoleWriteLine(MyComparer( )); ConsoleWriteLine(MyComparer((byte) )); ConsoleWriteLine(MyComparer((double) )); ConsoleWriteLine(MyComparer( )); 测试结果 True False True False False 最后提一个简单的问题供大家思考如果我们需要将字符串动态转换成我们自己定义的复杂类型 如何实现呢? 比如我们有一个结构 struct UInt { public ulong Low; public ulong High; } 我们将这个结构的实例对象传入到函数 ConsoleWriteLine(MyComparer((UInt) )); 这样可以吗?怎样做才能做到呢? |