我有一个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);
}
答案 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.aspx和http://msdn.microsoft.com/en-us/library/bb384043.aspx。