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

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

作者: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) 函数。

 

            MethodInfo parseMethod  =   null ;

            
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 这个参数。

 

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

 

 

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

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

    }

}

 

下面这个是根据"流言社"的 评论改进的。谢谢"流言社"

     public   class  ConvertString
    
{
        
public   static   object  ToType(Type type,  string  value)
        
{
            
return  System.ComponentModel.TypeDescriptor.GetConverter(type).ConvertFrom(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( 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 " ));

 

 测试结果


True
False
True
False
False

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

比如我们有一个结构

struct UInt128

{

public ulong Low;

public ulong High;

}

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值