给定一个类型和一个字符串,您是否可以尝试在不插入类型的情况下将字符串转换为该类型
本文关键字:类型 一个 字符串 情况下 插入 转换 是否 | 更新日期: 2023-09-27 18:36:10
我有一个List<Type>
,它表示来自自定义脚本语言的基于文本的命令的签名。我正在尝试确定如何将String[]
解析为对象类型与List<Type>
相关的List<object>
。基本上给定一个Type t
我想尝试对那个Type
投String s
.
到目前为止,我有这个
Type t = ...;
String s = ...;
if(Convert.ChangeType(s, t) != null)
{
}
在考虑了更多之后,我怀疑Convert.ChangeType
是否正确。它旨在简单地更改给定对象的类型,而不是"解析"它。鉴于您不能简单地执行(double)"ImAString"
我认为此方法将用于在"直接"可铸造的对象类型之间进行转换。
对此有什么通用的解决方案吗?还是唯一的方法是在给定的Type
上创建一个大型switch
并在每种情况下进行解析(将来很可能在交换机中缺少类型)?
编辑:此外,ChangeType
的返回类型是对象。我假设如果我做一个retObjectFromChange is double
是正确的(假设我将类型更改为双精度)?
Convert.ChangeType()
会在可能的情况下将字符串解析为数字,对不是有效数字的字符串引发异常。
注意:如果要在自己的自定义类型之间进行大量转换,则可能需要改用TypeConverter
。 (TypeConverter
在将两个基元类型(如 string
)转换为基元类型时会更好地工作。
看:使用 "Convert.ChangeType()" 将 System.String 一般转换为任何复杂类型
编辑:是的,假设没有引发异常,Convert.ChangeType("1.02", typeof(double)) is double
的计算结果应为 true。
当前的实现。我发现 Guid、DateTime、枚举和可为空是我的边缘情况。我输入了逻辑来处理空字符串和空值。我对一些原语进行了特定的处理,因为我发现 TypeConverter 与这些基元相比很慢,它们是我的一般情况。
public object GetValue(string readerValue, Type conversionType)
{
// if the type is a string, just return the value with no conversion
if (conversionType == typeof(string) || conversionType == typeof(object))
{
return readerValue;
}
// if the field has a value try to cast it
if (!string.IsNullOrWhiteSpace(readerValue))
{
readerValue = readerValue.Trim();
if (conversionType.IsEnum)
{
return Enum.Parse(conversionType, readerValue);
}
else
{
Type underlyingType = Nullable.GetUnderlyingType(conversionType) ?? conversionType;
if (underlyingType == typeof(int))
{
return int.Parse(readerValue);
}
else if (underlyingType == typeof(bool))
{
return bool.Parse(readerValue);
}
else if (underlyingType == typeof(DateTime))
{
return DateTime.Parse(readerValue);
}
else if (underlyingType == typeof(double))
{
return double.Parse(readerValue);
}
else if (underlyingType == typeof(long))
{
return long.Parse(readerValue);
}
else if (underlyingType == typeof(Guid))
{
return Guid.Parse(readerValue);
}
else
{
// GetConverter and ConvertFrom are both slow, so only use it in a fallback
TypeConverter converter = TypeDescriptor.GetConverter(underlyingType);
return converter.ConvertFrom(readerValue);
}
}
}
// return null for nullable generic primitives
else if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
return null;
}
// return the default value for non nullable primitive types
else if (conversionType.IsValueType)
{
return Activator.CreateInstance(conversionType);
}
// return null for reference types
else
{
return null;
}
}
一个巨大的边缘情况是,如果 conversionType 为 null,这将爆炸。就在这里:
if (conversionType.IsEnum)
第二个检查也是有问题的,对象可能只是一个空的框 对象o = null; 例如,看看这段代码,它会发出警告,但编译得很好。 如果 O 为空 类型现在为空。我可以再深入一点,但还有其他原因,我不会在第二种情况下开火例如
Object o = null;
Type T = o?.GetType() ?? null;
也签名与未签名。这个解决方案中也有很多反思。这就是我要做的,通过使用和扩展TypeCode构建TypeMap,您可以轻松获得25种类型而无需反射
if (conversionType == typeof(string) && !String.IsNullOrWhiteSpace(readerValue))
{
return conversionType;
}
所以现在我们知道了事情,我们不想要字符串,我们有 null。现在我们必须看看我们是否嵌套,if(typeof(conversiontype).isnested
Type.GetTypeCode(conversionType);
在实践中,最好创建一个真正的 Dictionary<int、String>以便您可以添加自己的类型。更好的是,如果转换为空,则返回 0。您还可以即时创建类型映射词典并缓存它。它大约有二十种类型,正如我所说,可以扩展。
var TypeMap = Enum.GetValues(typeof(TypeCode)).Cast<TypeCode>().ToDictionary(t=>(int)t, f=>f.ToString());
之后,只需通过对字符串调用 getType 来获取类型。接受所有这些字符串作为参数。
now here's the fun part, i've got about 30 or 40 types in my hashmap however if it's not in there
try
{
Type T = Type.GetType(CustomTypeMap[TypeCode])
if(TypeCode != 0)
// see if the type is nested and repeat
//the cases I had to add to TypeCode myself were GUID, ENUM,
}
if you want to skip a step your dictionary can look like this as well
Dictionary<int, Type> IntToType = new Dictionary<int, Type>()
{
[1] = typeof(bool),
[2] = typeof(int),
[3] = typeof(double),
[4] = typeof(string),
};