我有一个可以为空的int类?数据类型设置为序列化为xml元素。有没有办法设置它,所以如果值为null,xml序列化程序将不会序列化该元素?
我尝试添加[System.Xml.Serialization.XmlElement(IsNullable = false)]属性,但是我得到一个运行时序列化异常,说有一个反映该类型的错误,因为“可能没有设置IsNullable”对于Nullable类型,为'false'。考虑使用'System.Int32'类型或从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>
但是对于null的ID,我根本不需要ID元素,主要是因为当我在MSSQL中使用OPENXML时,对于看起来像
的元素,它返回0而不是null答案 0 :(得分:144)
XmlSerializer支持ShouldSerialize{Foo}()
模式,因此您可以添加方法:
public bool ShouldSerializeID() {return ID.HasValue;}
还有{Foo}Specified
模式 - 不确定XmlSerializer是否支持该模式。
答案 1 :(得分:25)
我正在使用这种微模式来实现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; } }
这为用户提供了正确的界面而且没有任何妥协,在序列化时仍然做正确的事情。
答案 2 :(得分:12)
我找到了一个使用两个属性的解决方法。一个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());
}
}
}
答案 3 :(得分:6)
我将你正在做的事情做得更加通用了。我们真正想要的是让Nullable具有略微不同的序列化行为。我使用Reflector来构建我自己的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&lt; int&gt;),但除此之外,所有行为都保持不变。
答案 4 :(得分:1)
不幸的是,您描述的行为准确地记录在XmlElementAttribute.IsNullable的文档中。
答案 5 :(得分:1)
非常有用的帖子帮助了很多。
我选择使用Scott对Nullable(Of T)数据类型的修订,但是当它为空时,发布的代码仍然序列化Nullable元素 - 尽管没有“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)指定模式,因为这需要向我的对象添加冗余属性的存储桶负载,而使用新的Nullable类型只需要重新输入属性。