问题 连载bool?错误反映类型


我有一个类似的课程

   [Serializable]
    public class MyClass
    {
        [XmlAttribute]
        public bool myBool { get; set; }
    }

但是当xml中不存在该属性时,这会将bool的值序列化为false。 当属性不在xml中时,我希望该属性为null。

所以我试过这个

[Serializable]
public class MyClass
{
    [XmlAttribute]
    public bool? myBool { get; set; }
}

但后来串行器错误

Type t = Type.GetType("Assembly.NameSpace.MyClass");
                XmlSerializer mySerializer = new XmlSerializer(t); //error "There was an error reflecting type"

请举个例子,我可以做到这一点。我知道在SO上有一些相关的问题,但没有任何东西能说明如何用可空的bool克服反射误差。谢谢。


12576
2018-03-30 12:00


起源



答案:


您需要使用“* Specified”字段模式来控制它(请参阅“控制生成的XML”) MSDN):

[Serializable]
public class MyClass
{
    [XmlAttribute]
    public bool myBool { get; set; }

    [XmlIgnore]
    public bool myBoolSpecified;
}

逻辑现在变成:

  • 如果 !myBoolSpecified, 然后 myBool 在逻辑上 null
  • 否则使用 true 要么 false 的 myBool

10
2018-03-30 12:14



@Aliostad:我很欣赏你的方法的优点,但是如果XML结构不可修改,那么这个结构将无效。 - Jon
这看起来很棒,但似乎没有用。 “{}指定”是一个神奇的名字吗?我在吸气器中需要一些逻辑吗? - Jules
@Jules:是的,这是一个神奇的名字。在链接页面上搜索“以propertyNameSpecified的形式创建模式”。如果它不起作用,请显示您当前的代码。 - Jon
@Jon现在我明白了! +1 - Aliostad
我有这个问题。虽然在反序列化时它确实省略了属性,但是当属性具有值时,它不会将属性序列化为属性。我需要解决方案在两个方向上工作。 - Jules


答案:


您需要使用“* Specified”字段模式来控制它(请参阅“控制生成的XML”) MSDN):

[Serializable]
public class MyClass
{
    [XmlAttribute]
    public bool myBool { get; set; }

    [XmlIgnore]
    public bool myBoolSpecified;
}

逻辑现在变成:

  • 如果 !myBoolSpecified, 然后 myBool 在逻辑上 null
  • 否则使用 true 要么 false 的 myBool

10
2018-03-30 12:14



@Aliostad:我很欣赏你的方法的优点,但是如果XML结构不可修改,那么这个结构将无效。 - Jon
这看起来很棒,但似乎没有用。 “{}指定”是一个神奇的名字吗?我在吸气器中需要一些逻辑吗? - Jules
@Jules:是的,这是一个神奇的名字。在链接页面上搜索“以propertyNameSpecified的形式创建模式”。如果它不起作用,请显示您当前的代码。 - Jon
@Jon现在我明白了! +1 - Aliostad
我有这个问题。虽然在反序列化时它确实省略了属性,但是当属性具有值时,它不会将属性序列化为属性。我需要解决方案在两个方向上工作。 - Jules


看一下 这个 有关处理可空字段和XML属性的信息。有类似的  这里也。基本上,序列化程序无法处理定义为可为空的XML属性字段,但有一种解决方法。

即2个属性,一个包含可空(不是XML存储),另一个在读/写中使用(XML属性存储为字符串)。也许这可能是你需要的?

private bool? _myBool;
[XmlIgnore]
public bool? MyBool
{
    get
    {
        return _myBool;
    }
    set
    {
        _myBool = value;
    }
}

[XmlAttribute("MyBool")]
public string MyBoolstring
{
    get
    {
        return MyBool.HasValue
        ? XmlConvert.ToString(MyBool.Value)
        : string.Empty;
    }
    set
    {
        MyBool =
        !string.IsNullOrEmpty(value)
        ? XmlConvert.ToBoolean(value)
        : (bool?)null;
    }
}

3
2018-03-30 12:25





您可以使用 XmlElementAttribute.IsNullable

[Serializable]
public class MyClass
{
    [XmlElement(IsNullable = true)]
    public bool? myBool { get; set; }
}

2
2017-12-18 07:58



只有当您可以选择序列化为元素而不是属性时,这才可行 - Rowland Shaw


问题是,a 可以为nullable类型定义为元素(默认值)而不是Attribute。

原因是当值为null时,它可以表示为 <mybool xs:nil="true"/> 因此 不能表示为属性

看看这个片段:

[Serializable]
public class MyClass
{
    // removed the attribute!!!
    public bool? myBool { get; set; }
}

和:

XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
var stream = new MemoryStream();
serializer.Serialize(stream, new MyClass(){myBool = null});
Console.WriteLine(Encoding.UTF8.GetString(stream.ToArray()));

输出:

<?xml version="1.0"?>
<MyClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.o
rg/2001/XMLSchema-instance">
  <myBool xsi:nil="true" /> <!-- NOTE HERE !!! -->
</MyClass>

1
2018-03-30 12:13



谢谢,但这是我收到的xml中的属性,所以我无法控制它。有没有办法有一个可以为空的bool属性? - Jules
@Jules Jon的回答是正确的。 - Aliostad