给定一个类型和一个字符串,您是否可以尝试在不插入类型的情况下将字符串转换为该类型

本文关键字:类型 一个 字符串 情况下 插入 转换 是否 | 更新日期: 2023-09-27 18:36:10

我有一个List<Type>,它表示来自自定义脚本语言的基于文本的命令的签名。我正在尝试确定如何将String[]解析为对象类型与List<Type>相关的List<object>。基本上给定一个Type t我想尝试对那个TypeString 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),
    };
相关文章: