如何将字符串动态转换为指定的值类型

开发 后端
我们经常会遇到将字符串转换为值类型的问题,比如"123" 转换为一个Int32类型,这个很简单,我们只要调用int.Parse 函数就可以实现。笔者今天要说的是,一些应用中往往在编码阶段无法知道字符串需要转换成的值类型的具体类型,而需要在运行时动态指定类型进行转换,遇到这种问题,我们如何解决?

先看一个字符串动态转换的典型例子

如下函数,我们只知道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.
  • 2.
  • 3.

要解决这个问题,我们需要解决两个基本问题。

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)
  • 1.

 type 为指定的类型,value 为输入的字符串。

首先我们知道所有的基本值类型都有一个叫 Parse 静态函数,我们只要把这个静态函数反射出来,就可以通过这个静态函数将字符串动态转换成对应的值类型。

下面代码给出如何反射出这个静态函数。通过向对象type(Type类型)的GetMethods 函数输入 BindingFlags.Static
    | BindingFlags.Public 参数,我们可以枚举出这个类型所有的静态公共函数。

然后我们判断这个函数的名称是否为 "Parse" ,由于 Parse 函数有多个重载,但一个参数的重载只有 Parse (String)

所以我们需要判断mi 只有一个参数,这时取到的 mi 就是 Parse (String) 函数。

MethodInfo parseMethod = null;

foreach (MethodInfo mi in type.GetMethods(BindingFlags.Static     | BindingFlags.Public)) {     if (mi.Name == "Parse" && mi.GetParameters().Length == 1)     {   parseMethod = mi;   break;     } }

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

接下来就是如何调用这个函数来动态转换字符串了。

如下面代码,我们调用MethodInfo 的 Invoke 方法来动态调用这个函数,由于是静态函数,第一个参数 obj 传入null. 并在第二个参数中带入value 这个参数。

parseMethod.Invoke(null, new object[] { value });
  • 1.

下面给出字符串动态转换为指定类型的完整代码

using System;
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 });   }     } }

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.

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(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(2, "1", "3")); 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"));  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.

 测试结果

True
False
True
False
False
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

最后提一个简单的问题,供大家思考,如果我们需要将字符串动态转换成我们自己定义的复杂类型,如何实现呢?

比如我们有一个结构

struct UInt128

{

public ulong Low;

public ulong High; }

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

我们将这个结构的实例对象传入到函数

Console.WriteLine(MyComparer((UInt128)2, "1", "3"));
  • 1.

这样可以吗?怎样做才能做到呢?

【编辑推荐】

  1. C# 2010命名和可选参数的新特性
  2. 详解C# 4.0中必选参数与可选参数混合的问题
  3. 在.NET上如何根据字符串动态创建控件
  4. 检测含有中文字符串的实际长度
  5. 深入理解C# 3.0的五项主要改进
责任编辑:彭凡 来源: cnblogs
相关推荐

2024-02-19 15:38:08

JsonPython字符串

2021-12-29 16:40:54

Python语言字符串

2009-11-25 16:55:45

PHP函数explod

2024-01-04 09:17:03

前端开发CSV 格式JSON 字符串

2009-07-15 16:56:59

Jython类型Java类型

2023-10-16 09:26:48

CSS类型转换

2021-11-29 00:17:41

JS符串转换

2009-12-01 14:00:37

PHP字符串转换为数值

2017-05-25 15:14:36

2020-12-17 08:08:15

CentOS

2024-03-12 07:35:39

Python字符串列表

2021-08-26 09:46:22

JavaScript字符串URL

2010-03-31 19:15:25

Oracle函数

2024-05-30 08:40:41

大型语言模型LLM人工智能

2009-07-31 14:09:41

c#时间格式转换

2016-12-30 13:16:51

字符串算法代码

2010-11-26 14:09:32

MySQL内置函数

2010-09-09 11:48:00

SQL函数字符串

2023-03-13 07:43:51

PHP类型转换

2011-04-08 10:16:13

文本文件ACCESS数据库
点赞
收藏

51CTO技术栈公众号