【问题标题】:Why isn't an implicit conversion from int to intBox working in Json.decode or default modelbinding?为什么从 int 到 intBox 的隐式转换不能在 Json.decode 或默认模型绑定中工作?
【发布时间】:2017-02-07 16:50:57
【问题描述】:

编辑:删除了问题的第一部分,因为它具有误导性且不完全相关。

由于各种原因,我已经到了可以真正使用将我的一些 Post body 参数装箱到他们的模型中的地步。

我开始这个只是接受默认的模型绑定器就可以工作™,它确实如此,但不适用于 ints(?!)。示例:

public class IntBox
{
    public int Value;

    public IntBox(int value)
    {
        Value = value;
    }

    public static implicit operator IntBox(int value)
    {
        return new IntBox(value);
    }
}

public class StringBox
{
    public string Value;

    public StringBox(string value)
    {
        Value = value;
    }

    public static implicit operator StringBox(string value)
    {
        return new StringBox(value);
    }
}

public class BoolBox
{
    public bool Value;

    public BoolBox(bool value)
    {
        Value = value;
    }

    public static implicit operator BoolBox(bool value)
    {
        return new BoolBox(value);
    }
}

public class NeedQuery : StateFullQuery
{
    public StringBox[] TestStrings { get; set; } //"TestStrings":["a","b"]
    public IntBox[] TestInts { get; set; } //"TestInts":[1,2,3,4]
    public BoolBox[] TestBools { get; set; } //"TestBools":[true,false]
}

//Inside Controller:
public string Post([FromBody]NeedQuery query)
{
    //At this point query.TestStrings contains two StringBoxes with the expected values. As does query.TestBools
    // However, query.TestInts is empty.
}

我错过了什么?! Ints 有什么特别之处以至于它们不能被 Modelbinder 隐式转换?我该如何解决这个问题?

非常感谢您对此的帮助;如果没有大的重写,我会被阻止,直到我弄明白为止。

注意:当我说我需要对 int 值进行装箱时,这是为了帖子而对问题的简化,它比简单地装箱值要复杂一些。

【问题讨论】:

    标签: c# json asp.net-web-api2 model-binding implicit-conversion


    【解决方案1】:

    想通了。

    这不起作用:

    public class IntBox
    {
        public int Value;
    
        public IntBox(int value)
        {
            Value = value;
        }
    
        public static implicit operator IntBox(int value)
        {
            return new IntBox(value);
        }
    }
    

    这确实有效:

    public class IntBox
    {
        public int Value;
    
        public IntBox(int value)
        {
            Value = value;
        }
    
        public static implicit operator IntBox(Int64 value)
        {
            return new IntBox(value);
        }
    }
    

    显然,64/32 位转换存在一些愚蠢之处。我可能不得不为 32 位和 64 位整数实现我的隐式转换,但至少我可以停止拉扯我的头发。也许这会在未来对其他人有所帮助。

    【讨论】:

      【解决方案2】:

      发生这种情况的原因是(简而言之)隐式转换是在编译时推断出来的,而模型绑定器在运行时使用反射来设置值,此时有两种不同的 - 不兼容的 - 类型。

      处理此类情况的最简单解决方案通常是在模型上拥有(例如)int[] 属性,绑定到该属性并让它简单地手动映射到IntBox[] 属性(例如通过自定义访问器) .

      我不会发布“完整”解决方案,因为-正如您所说-您的示例已简化;但是,希望这些信息足以让您了解和解决问题。

      【讨论】:

      • 如果是这种情况,为什么在第二个示例中隐式转换为 string 和 bool 有效,而 Int 无效?
      • @Glitcher 这是一个很好的问题 - 我很惊讶它的工作原理(dotnetfiddle.net/cztCKK)。如果这是您看到的行为,那么在默认模型绑定器到达设置属性的常用路径之前,这些属性肯定发生了其他事情......
      • 感谢您的回答,我目前正在解决这个问题,但我真的很想知道为什么它会如此严重地失败
      • 它失败的原因是因为它使用PropertyDescriptor.SetValue 在运行时设置属性——我更感兴趣的是为什么它在其他情况下显然有效
      • 澄清一下,你是说 [FromBody] 使用 PropertyDescriptor.SetValue 吗?因为如果走 Json.Decode 路线,所有隐含转换都会失败。只有在使用 [FromBody] 时,只有 int 才会失败(它会默默地这样做)
      猜你喜欢
      • 1970-01-01
      • 2015-01-11
      • 2013-05-23
      • 2011-12-24
      • 2018-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-27
      相关资源
      最近更新 更多