我正在上第一堂课,然后对其进行序列化。我从未使用过序列化,并且遇到了一些问题。这是课程代码:
<XmlRoot([Namespace]:="FatturaElettronica")>
Public Class FatturaElettronica
Public quantity As Integer
Sub New()
FatturaElettronicaHeader = New FatturaElettronicaHeader
End Sub
Property FatturaElettronicaHeader As FatturaElettronicaHeader
End Class
Public Class FatturaElettronicaHeader
Sub New()
DatiTrasmissione = New DatiTrasmissione
End Sub
Property DatiTrasmissione As DatiTrasmissione
End Class
Public Class DatiTrasmissione
Sub New()
Idtrasmittente = New idTrasmittente
ContattiTrasmittente = New ContattiTrasmittente
End Sub
Property Idtrasmittente As idTrasmittente
Property ProgressivoInvio As String
Property FormatoTrasmissione As FormatoTrasmissioneType
Property CodiceDestinatario As String
Property ContattiTrasmittente As ContattiTrasmittente
Property PecDestinatario As String
End Class
Public Class idTrasmittente
Property IdPaese As String
Property IdCodice As String
End Class
Public Class ContattiTrasmittente
Property Telefono As String
Property Email As String
End Class
Public Enum FormatoTrasmissioneType
FPA12
FPR12
End Enum
以下是我用于测试的一些代码:
Dim fattEle As New FatturaElettronica
Dim ns2 As New Xml.Serialization.XmlSerializerNamespaces()
ns2.Add("p", "FatturaElettronica")
Dim ser As Xml.Serialization.XmlSerializer = New Xml.Serialization.XmlSerializer(fattEle.GetType)
Dim stream As New IO.FileStream("c:/lavoro/example2.xml", IO.FileMode.Create)
ser.Serialize(stream, fattEle, ns2)
stream.Close()
这是我的输出XML:
<?xml version="1.0"?>
<p:FatturaElettronica xmlns:p="FatturaElettronica">
<p:FatturaElettronicaHeader>
<p:DatiTrasmissione>
<p:Idtrasmittente />
<p:FormatoTrasmissione>FPA12</p:FormatoTrasmissione>
<p:ContattiTrasmittente />
</p:DatiTrasmissione>
</p:FatturaElettronicaHeader>
</p:FatturaElettronica>
首先,我想仅在根p:
之前添加FatturaElettronica
。
第二,FormatoTrasmissione
属性是Enum
,但是在我的代码中没有设置任何内容。那么,为什么序列化假定值为FPA12
而未分配该值?
最后但并非最不重要的一点...我想不序列化未填充的属性。 ContattiTrasmittente
属性为空,但已序列化。为什么?
答案 0 :(得分:1)
您在这里有三个独立的问题。让我们崩溃然后崩溃。
第一 ,我只想在根p:
之前添加FatturaElettronica
。因为通过XmlRootAttribute.Namespace
属性指定的名称空间将递归地应用于所有子元素,除非另有覆盖。
由于您不希望这样做,因此最简单的预防方法是将<XmlType([Namespace]:="")>
应用于FatturaElettronica
。这会将空名称空间应用于FatturaElettronica
的所有子元素,取代XmlRootAttribute.Namespace
,该子元素现在仅应用于根元素本身。
第二 ,FormatoTrasmissione
属性是Enum
,但是在我的代码中没有设置任何属性。那么,为什么序列化假定值为FPA12
而未分配该值?
默认情况下,XmlSerializer
序列化所有非空公共属性和字段。由于enum
是一种值类型,因此从定义上讲它不是null,因此枚举值属性总是被序列化的。
由于您不希望这样做,因此可以使用XML Schema Binding Support: MinOccurs Attribute Binding Support中记录的{propertyName}Specified
条件序列化模式,并添加一个FormatoTrasmissioneSpecified
布尔属性,该属性可跟踪{{1} }属性曾经明确设置过。如果不是,则序列化程序将不会序列化属性。
第三 ,我不希望序列化未填充的属性。 FormatoTrasmissione
属性为空,但已序列化。为什么?发生这种情况的原因与ContattiTrasmittente
属性被序列化的原因相同:FormatoTrasmissione
将序列化所有非null的公共属性,并且您为XmlSerializer
显式分配了一个值在ContattiTrasmittente
构造函数中:
DatiTrasmissione
由于您不希望这样做,因此可以使用Properties in Windows Forms Controls: Defining Default Values with the ShouldSerialize and Reset Methods中记录的Public Class DatiTrasmissione
Sub New()
Idtrasmittente = New idTrasmittente
ContattiTrasmittente = New ContattiTrasmittente
End Sub
条件序列化模式,并添加一个布尔方法ShouldSerialize{PropertyName}()
,当{{1 }}为空,或其所有属性为空。由于您要分配多个属性而未设置任何子值,因此可能需要添加多个此类方法。另外,您可以重新考虑设计,只在实际需要时才分配嵌套属性。
有关这两个条件序列化模式的更多详细信息,请参见 ShouldSerialize*() vs *Specified Conditional Serialization Pattern 。
将所有这些放在一起,您的代码应类似于:
ShouldSerializeContattiTrasmittente()
正在工作的vb.net提琴here。