8

我有一个string和一个Type,我想返回string转换为那个的值Type

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

这将返回一个object我可以在属性集值调用中使用的:

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

这适用于大多数基本类型,但可为空的除外。

[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方法的行为。

我追求的行为:

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

结果

就像基里尔的回答一样,只有一个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);
}
4

6 回答 6

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);
}
于 2012-11-14T15:18:59.433 回答
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);
}
于 2012-11-14T15:15:23.417 回答
2

试试这个:

prop.IsGenericType && Nullable.GetUnderlyingType(prop) == value.GetType()
于 2012-11-14T15:11:01.117 回答
2

这里的问题是 的返回值ChangeType以及您的方法是object. 当您将任何可空类型装箱时object,它不会将可空类型装箱。如果该值在运行时实际上为 null ,则将 a 框null起来,如果它有值,则将实际的底层值(而不是可为 null 的版本)框起来。

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

这在任何其他类型的一般情况下都不会发生;Nullable<T>有特殊的编译器支持来做到这一点。您基本上还需要Nullable在代码中使用特殊情况;如果您的方法传递了一个Nullable类型,您需要首先检查对象是否null存在 ,如果没有 null,请改用底层类型Nullable

于 2012-11-14T15:25:26.603 回答
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
于 2012-11-14T16:24:40.237 回答
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

于 2012-11-14T15:17:18.577 回答