从字符串转换为任何基本类型

时间:2012-11-14 15:08:09

标签: c#

我有一个string和一个Type,我希望将string转换为Type的值。

public static object StringToType(string value, Type propertyType)
{
    return Convert.ChangeType(value, propertyType, CultureInfo.InvariantCulture);
}

这将返回一个object,我可以在属性集值调用中使用{<1}}:

public static void SetBasicPropertyValueFromString(object target,
                                                   string propName,
                                                   string value)   
{
  PropertyInfo prop = target.GetType().GetProperty(propName);
  object converted = StringToType(value, prop.PropertyType);
  prop.SetValue(target, converted, null);
}

这适用于大多数基本类型,除了nullables。

[TestMethod]
public void IntTest()
{ //working
    Assert.AreEqual(1, ValueHelper.StringToType("1", typeof (int)));
    Assert.AreEqual(123, ValueHelper.StringToType("123", typeof (int)));
}

[TestMethod]
public void NullableIntTest()
{ //not working
    Assert.AreEqual(1, ValueHelper.StringToType("1", typeof (int?)));
    Assert.AreEqual(123, ValueHelper.StringToType("123", typeof (int?)));
    Assert.AreEqual(null, ValueHelper.StringToType(null, typeof (int?)));
}

NullableIntTest在第一行失败:

  

System.InvalidCastException:从'System.String'到'System.Nullable`1 [[System.Int32,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]'的无效演员表。

如果类型可以为空并且改变StringToType方法的behaiour,我很难确定。

我追随的行为:

如果string为null或为空,则返回null,否则按照非可空类型进行转换。

结果

像Kirill的回答一样,只有一次ChangeType电话。

public static object StringToType(string value, Type propertyType)
{
    var underlyingType = Nullable.GetUnderlyingType(propertyType);
    if (underlyingType != null)
    {
        //an underlying nullable type, so the type is nullable
        //apply logic for null or empty test
        if (String.IsNullOrEmpty(value)) return null;
    }
    return Convert.ChangeType(value,
                              underlyingType ?? propertyType,
                              CultureInfo.InvariantCulture);
}

6 个答案:

答案 0 :(得分:6)

您不能在可空类型上使用Convert.ChangeType,因为它不是从IConvertible继承的。你应该改写你的方法。

public static object StringToType(string value, Type propertyType)
{
   var underlyingType = Nullable.GetUnderlyingType(propertyType);
   if(underlyingType == null)
          return Convert.ChangeType(value, propertyType,  CultureInfo.InvariantCulture);
   return String.IsNullOrEmpty(value)
          ? null
          : Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture);
}

答案 1 :(得分:3)

public static object StringToType(string value, Type propertyType)
{
   var underlyingType = Nullable.GetUnderlyingType(propertyType);
   return underlyingType == null ? Convert.ChangeType(value, propertyType, CultureInfo.InvariantCulture) : Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture);
}

答案 2 :(得分:2)

试试这个:

prop.IsGenericType && Nullable.GetUnderlyingType(prop) == value.GetType()

答案 3 :(得分:2)

这里的问题是ChangeType的返回值以及您的方法是object。当您将任何可空类型包装到object时,它不会将可空类型包装起来。如果该值在运行时实际上为空,则会设置null,如果它有一个值,则会将实际的基础值(而不是可为空的版本)包装起来。

int? i = 5;
object o = i;
Type t = o.GetType();//will be `int`, not `Nullable<int>`

在任何其他类型的一般情况下都不会发生这种情况; Nullable<T>具有特殊的编译器支持来执行此操作。您基本上也需要在代码中使用特殊情况Nullable;如果您的方法是Nullable类型,则需要首先检查null的对象,如果不是null,请使用Nullable的基础类型。

答案 4 :(得分:1)

在Kirill Bestemyanov'代码片段的帮助下的代码:

public static object StringToType<T>(string value)
{
   return StringToType(value, typeof(T));
}

public static object StringToType(string value, Type propertyType)
{
   var underlyingType = Nullable.GetUnderlyingType(propertyType);
   if(underlyingType == null)
     return Convert.ChangeType(value, propertyType, CultureInfo.InvariantCulture);
   return String.IsNullOrEmpty(value)
     ? null
     : Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture);
}

用法(WL只写入控制台)。你是对的,泛型方法不能使用int?作为通用参数。

WL(StringToType("1", typeof (int?))); // -> 1
WL(StringToType<int>("1"));           // -> 1
WL(StringToType<int?>("1"));          // error, not compilable
WL(StringToType<Nullable<int>>("1")); // -> 1

答案 5 :(得分:0)

您必须为要支持的每种类型使用适当的强制转换方法。

int parsedInt;
int.TryParse("1", out parsedInt);

double parsedDouble;
double.TryParse("0.0d", out parsedDouble);

编译器不可能根据字符串的内容确定类型。有关从字符串转换为标量类型的详细信息,请参阅以下链接:http://msdn.microsoft.com/en-us/library/bb397679.aspxhttp://msdn.microsoft.com/en-us/library/bb384043.aspx