【问题标题】:TypeConverters broken for primitive types?TypeConverters 因原始类型而损坏?
【发布时间】:2012-05-16 10:33:12
【问题描述】:

我遇到了DecimalConverterInt32Converter 类的问题,它们似乎返回了不一致的结果,如下面的简单控制台程序所示:

using System;
using System.ComponentModel;

class App
{
    static void Main()
    {
        var decConverter = TypeDescriptor.GetConverter(typeof(decimal));
        Console.WriteLine("Converter: {0}", decConverter.GetType().FullName);
        Console.WriteLine("CanConvert from int to decimal: {0}", decConverter.CanConvertFrom(typeof(int)));
        Console.WriteLine("CanConvert to int from decimal: {0}", decConverter.CanConvertTo(typeof(int)));

        Console.WriteLine();

        var intConverter =  TypeDescriptor.GetConverter(typeof(int));
        Console.WriteLine("Converter: {0}", intConverter.GetType().FullName);
        Console.WriteLine("CanConvert from int to decimal: {0}", intConverter.CanConvertTo(typeof(decimal)));
        Console.WriteLine("CanConvert to int from decimal: {0}", intConverter.CanConvertFrom(typeof(decimal)));
    }
}

由此产生的输出如下:

Converter: System.ComponentModel.DecimalConverter
CanConvert from int to decimal: False
CanConvert to int from decimal: True

Converter: System.ComponentModel.Int32Converter
CanConvert from int to decimal: False
CanConvert to int from decimal: False

除非我对 TypeConverters 的理解有误,否则以下内容应该成立:

TypeDescriptor.GetConverter(typeof(TypeA)).CanConvertFrom(typeof(TypeB))

应该给出与

相同的结果
TypeDescriptor.GetConverter(typeof(TypeB)).CanConvertTo(typeof(TypeA))

至少在System.Int32System.Decimal 的情况下,它们不会。

我的问题是:有人知道这是否是设计使然吗?还是 C# 中原生类型的 TypeConverters 真的坏了?

【问题讨论】:

  • 我不明白在反序列化 JSON 时为什么需要将 int 转换为 decimal,因为 JSON 包含字符串,而不是 ints。
  • 我已经扩展了我的问题以澄清。我意识到我可以通过确保将所有内容作为字符串序列化到浏览器中来处理这个问题,但这不是真正的问题,更多的是前奏。

标签: c# .net typeconverter


【解决方案1】:

根据MSDN documentation for Int32Converter...

此转换器只能将 32 位有符号整数对象转换为和 来自一个字符串。

我同意 cmets 中的 @svick,但我不明白为什么您首先需要通过 Int32 将 JSON 字符串反序列化为 Decimal。

【讨论】:

  • 我没有。 ASP.NET MVC 的默认 JSON 处理确实如此。通过 AJAX 提交 application/json 请求时,默认的 JavaScriptSerializer 会将所有整数反序列化为 Int32 对象。当系统尝试将这些 Int32 值映射回我的模型的 decimal 属性时,我遇到了麻烦。
  • @BryanRoss 你见过this StackOverflow question? 我怀疑它与你的问题非常相似,因为你需要将小数作为带引号的字符串传递。 JavaScriptSerializer 将错误地猜测类型并最终根据其错误的猜测尝试不适当的转换,但显式引用值将尝试字符串到类型的转换,这应该是一个更可行的解决方案。
  • 谢谢克里斯,我绝对同意你的观点,实际上我已经找到了这个解决方案。我仍然想知道为什么 TypeConverter 没有报告一致的功能。
  • @BryanRoss 将值与字符串转换是最常见的转换,据我所知,所有默认的TypeConverter 实现仅执行该单一转换。 Implementing a custom converter 也可能是扩展转换功能的一个选项。我还没有看到决定只实施一次转换的官方原因。
【解决方案2】:

在这种情况下,您根本不需要处理类型转换器。如果您想反序列化您的模型类,请执行以下操作:

serializer.Deserialize<Model>(json)

它会为您处理所有转换。

如果您确实需要手动进行转换,请使用Convert.ToDecimal(integer)(或Convert.ChangeType(integer, typeof(decimal))),它将正常工作。

【讨论】:

  • 使用 TypeConverters 的不是我的代码。它是 ASP.NET MVC 的。但是,问题是关于 TypeConverters 以及为什么它们会产生不一致的结果,而不是 JSON 序列化/反序列化。
  • 那么也许这不是你应该问的问题。我认为您在 JSON 反序列化方面做错了,这不是类型转换器的错。
  • 我发布的示例程序与 json 无关,但它表现出我描述和询问的行为。正如我之前所说,我的代码实际上并没有执行反序列化。这是 ASP.NET MVC 的代码。由于我询问的实际问题,JSON 请求中未加引号的数字值无法自动映射回十进制属性。不想在这里粗鲁,我完全知道如何解决我的特定 JSON 问题。这不是问题。我非常具体地询问 TypeConverters 在本机数字类型方面的行为。
猜你喜欢
  • 2012-09-07
  • 2011-09-25
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多