序列化一个可空的int
我有一个可空int的类? 数据types设置为序列化为一个XML元素。 有没有什么办法来设置它,所以如果值为null,xml序列化程序将不会序列化元素?
我试着添加[System.Xml.Serialization.XmlElement(IsNullable = false)]属性,但是我得到一个运行时序列化exception,说有一个错误反映了types,因为“IsNullable可能不会被设置为false '为Nullabletypes,请考虑使用'System.Int32'types或从XmlElement属性中删除IsNullable属性。
[Serializable] [System.Xml.Serialization.XmlRoot("Score", Namespace = "http://mycomp.com/test/score/v1")] public class Score { private int? iID_m; ... /// <summary> /// /// </summary> public int? ID { get { return iID_m; } set { iID_m = value; } } ... }
上面的类将会序列化为:
<Score xmlns="http://mycomp.com/test/score/v1"> <ID xsi:nil="true" /> </Score>
但是,对于ID为空的我根本不需要ID元素,主要是因为当我在MSSQL中使用OPENXML时,它返回一个0而不是null的元素,看起来像
XmlSerializer支持ShouldSerialize{Foo}()
模式,所以你可以添加一个方法:
public bool ShouldSerializeID() {return ID.HasValue;}
还有{Foo}Specified
模式 – 不知道XmlSerializer是否支持这个模式。
我正在使用这个微型模式来实现Nullable序列化:
[XmlIgnore] public double? SomeValue { get; set; } [XmlAttribute("SomeValue")] // or [XmlElement("SomeValue")] [EditorBrowsable(EditorBrowsableState.Never)] public double XmlSomeValue { get { return SomeValue.Value; } set { SomeValue= value; } } [EditorBrowsable(EditorBrowsableState.Never)] public bool XmlSomeValueSpecified { get { return SomeValue.HasValue; } }
这为用户提供了正确的界面,并且在序列化时仍然是正确的。
我想出了一个利用两个属性的解决方法。 一个int? 属性与一个XmlIgnore属性和被序列化的对象属性。
/// <summary> /// Score db record /// </summary> [System.Xml.Serialization.XmlIgnore()] public int? ID { get { return iID_m; } set { iID_m = value; } } /// <summary> /// Score db record /// </summary> [System.Xml.Serialization.XmlElement("ID",IsNullable = false)] public object IDValue { get { return ID; } set { if (value == null) { ID = null; } else if (value is int || value is int?) { ID = (int)value; } else { ID = int.Parse(value.ToString()); } } }
哇谢谢这个问题/答案真的帮了我。 我心脏Stackoverflow。
我做了一些更通用的事情。 我们真正要查找的是具有略微不同的序列化行为的Nullable。 我使用Reflector构build自己的Nullable,并在这里和那里添加了一些内容,使XML序列化按照我们所需的方式工作。 似乎工作得很好:
public class Nullable<T> { public Nullable(T value) { _value = value; _hasValue = true; } public Nullable() { _hasValue = false; } [XmlText] public T Value { get { if (!HasValue) throw new InvalidOperationException(); return _value; } set { _value = value; _hasValue = true; } } [XmlIgnore] public bool HasValue { get { return _hasValue; } } public T GetValueOrDefault() { return _value; } public T GetValueOrDefault(T i_defaultValue) { return HasValue ? _value : i_defaultValue; } public static explicit operator T(Nullable<T> i_value) { return i_value.Value; } public static implicit operator Nullable<T>(T i_value) { return new Nullable<T>(i_value); } public override bool Equals(object i_other) { if (!HasValue) return (i_other == null); if (i_other == null) return false; return _value.Equals(i_other); } public override int GetHashCode() { if (!HasValue) return 0; return _value.GetHashCode(); } public override string ToString() { if (!HasValue) return ""; return _value.ToString(); } bool _hasValue; T _value; }
你失去了让你的成员为int的能力? 等等(必须改用Nullable <int>),但除此之外,所有的行为都保持不变。
不幸的是,您所描述的行为在XmlElementAttribute.IsNullable的文档中被准确logging。
非常有用的发布帮助了很多。
我select使用Scott的Nullable(Of T)数据types的修订版本,但是发布的代码仍然会在Nulllable元素为Null的时候序列化,尽pipe没有“xs:nil ='true'”属性。
我需要强制序列化器完全删除标签,所以我只是在结构上实现了IXmlSerializable(这是在VB中,但你得到的图片):
'---------------------------------------------------------------------------- ' GetSchema '---------------------------------------------------------------------------- Public Function GetSchema() As System.Xml.Schema.XmlSchema Implements System.Xml.Serialization.IXmlSerializable.GetSchema Return Nothing End Function '---------------------------------------------------------------------------- ' ReadXml '---------------------------------------------------------------------------- Public Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements System.Xml.Serialization.IXmlSerializable.ReadXml If (Not reader.IsEmptyElement) Then If (reader.Read AndAlso reader.NodeType = System.Xml.XmlNodeType.Text) Then Me._value = reader.ReadContentAs(GetType(T), Nothing) End If End If End Sub '---------------------------------------------------------------------------- ' WriteXml '---------------------------------------------------------------------------- Public Sub WriteXml(ByVal writer As System.Xml.XmlWriter) Implements System.Xml.Serialization.IXmlSerializable.WriteXml If (_hasValue) Then writer.WriteValue(Me.Value) End If End Sub
我更喜欢这种方法来使用(foo)指定的模式,因为这需要增加冗余属性的桶负载到我的对象,而使用新的Nullabletypes只需要重新键入属性。