Controllare la serializzazione XML mediante attributi

Gli attributi possono essere utilizzati per controllare la serializzazione XML di un oggetto o per creare un flusso XML alternativo dallo stesso set di classi. Per altri dettagli sulla creazione di un flusso XML alternativo, vedere Procedura: Specificare un nome di elemento alternativo per un flusso XML.

Nota

Se è necessario che l'XML generato sia conforme alla sezione 5 del documento intitolato Simple Object Access Protocol (SOAP) 1.1 del World Wide Web Consortium (W3C), usare gli attributi elencati in Attributi per il controllo della serializzazione SOAP codificata.

Per impostazione predefinita, un nome di elemento XML è determinato dal nome della classe o del membro. In una classe denominata Book, un campo denominato ISBN produrrà un tag di elemento XML <ISBN>, come illustra l'esempio riportato di seguito:

Public Class Book
    Public ISBN As String
End Class
' When an instance of the Book class is serialized, it might
' produce this XML:
' <ISBN>1234567890</ISBN>.
public class Book
{
    public string ISBN;
}
// When an instance of the Book class is serialized, it might
// produce this XML:
// <ISBN>1234567890</ISBN>.

Se si desidera assegnare un nuovo nome all’elemento, questo comportamento predefinito può essere modificato. Il codice riportato di seguito mostra il modo in cui un attributo abilita tale funzione impostando la proprietà ElementName di una classe XmlElementAttribute:

Public Class TaxRates
   < XmlElement(ElementName = "TaxRate")> _
    Public ReturnTaxRate As Decimal
End Class
public class TaxRates {
    [XmlElement(ElementName = "TaxRate")]
    public decimal ReturnTaxRate;
}

Per altre informazioni sugli attributi, vedere Attributi. Per l'elenco degli attributi che controllano la serializzazione XML, vedere Attributi per il controllo della serializzazione XML.

Controllo della serializzazione di matrice

Gli attributi XmlArrayAttribute e XmlArrayItemAttribute controllano la serializzazione delle matrici. Tramite l'utilizzo di questi attributi, è possibile controllare il nome dell'elemento, lo spazio dei nomi e tipo di dati XML Schema (XSD), come definito nel documento W3C intitolato XML Schema Parte 2: Datatypes. È inoltre possibile specificare i tipi che possono essere inclusi in una matrice.

XmlArrayAttribute determinerà le proprietà dell'elemento XML di inclusione risultante dalla serializzazione di una matrice. Ad esempio, la serializzazione della matrice riportata di seguito, per impostazione predefinita comporterà la creazione di un elemento XML denominato Employees. L'elemento Employees conterrà una serie di elementi denominati dopo il tipo di matrice Employee.

Public Class Group
    Public Employees() As Employee
End Class
Public Class Employee
    Public Name As String
End Class
public class Group {
    public Employee[] Employees;
}
public class Employee {
    public string Name;
}

Un'istanza serializzata potrebbe essere simile al codice seguente:

<Group>
<Employees>
    <Employee>
        <Name>Haley</Name>
    </Employee>
</Employees>
</Group>

Tramite l'applicazione di un attributo XmlArrayAttribute, è possibile modificare il nome dell'elemento XML, come segue:

Public Class Group
    <XmlArray("TeamMembers")> _
    Public Employees() As Employee
End Class
public class Group {
    [XmlArray("TeamMembers")]
    public Employee[] Employees;
}

L'XML risultante potrebbe essere simile al codice seguente:

<Group>
<TeamMembers>
    <Employee>
        <Name>Haley</Name>
    </Employee>
</TeamMembers>
</Group>

XmlArrayItemAttribute, d'altra parte, controlla il modo in cui vengono serializzati gli elementi contenuti nella matrice.

Nota

L'attributo viene applicato al campo che restituisce la matrice.

Public Class Group
    <XmlArrayItem("MemberName")> _
    Public Employee() As Employees
End Class
public class Group {
    [XmlArrayItem("MemberName")]
    public Employee[] Employees;
}

L'XML risultante potrebbe essere simile al codice seguente:

<Group>
<Employees>
    <MemberName>Haley</MemberName>
</Employees>
</Group>

Serializzazione delle classi derivate

Un altro utilizzo di XmlArrayItemAttribute è quello di consentire la serializzazione di classi derivate. Ad esempio, al precedente esempio è possibile aggiungere un'altra classe denominata Manager che deriva da Employee. Se non si applica XmlArrayItemAttribute, il codice provocherà un errore in fase di esecuzione perché il tipo di classe derivata non verrà riconosciuto. Per risolvere questo problema, applicare due volte l'attributo, impostando ogni volta la proprietà Typeper ciascun tipo accettabile (base e derivato).

Public Class Group
    <XmlArrayItem(Type:=GetType(Employee)), _
    XmlArrayItem(Type:=GetType(Manager))> _
    Public Employees() As Employee
End Class
Public Class Employee
    Public Name As String
End Class
Public Class Manager
Inherits Employee
    Public Level As Integer
End Class
public class Group {
    [XmlArrayItem(Type = typeof(Employee)),
    XmlArrayItem(Type = typeof(Manager))]
    public Employee[] Employees;
}
public class Employee {
    public string Name;
}
public class Manager:Employee {
    public int Level;
}

Un'istanza serializzata potrebbe essere simile al codice seguente:

<Group>
<Employees>
    <Employee>
        <Name>Haley</Name>
    </Employee>
    <Employee xsi:type = "Manager">
        <Name>Ann</Name>
        <Level>3</Level>
    </Employee>
</Employees>
</Group>

Serializzazione di una matrice come sequenza di elementi

È possibile anche serializzare una matrice come un'unica sequenza di elementi XML applicando un attributo XmlElementAttribute al campo che restituisce la matrice nel modo riportato di seguito:

Public Class Group
    <XmlElement> _
    Public Employees() As Employee
End Class
public class Group {
    [XmlElement]
    public Employee[] Employees;
}

Un'istanza serializzata potrebbe essere simile al codice seguente:

<Group>
<Employees>
    <Name>Haley</Name>
</Employees>
<Employees>
    <Name>Noriko</Name>
</Employees>
<Employees>
    <Name>Marco</Name>
</Employees>
</Group>

Un altro modo per differenziare i due flussi XML è quello di utilizzare lo strumento XML Schema Definition per generare i file del documento XML Schema (XSD) dal codice compilato. Per altri dettagli sull'uso dello strumento, vedere Strumento XML Schema Definition e serializzazione XML. Se al campo non è applicato alcun attributo, lo schema descrive l'elemento nel modo riportato di seguito:

<xs:element minOccurs="0" maxOccurs ="1" name="Employees" type="ArrayOfEmployee" />

Se al campo è applicato l'attributo XmlElementAttribute, lo schema risultante descrive l'elemento nel modo riportato di seguito:

<xs:element minOccurs="0" maxOccurs="unbounded" name="Employees" type="Employee" />

Serializzazione di un ArrayList

La classe ArrayList contiene una raccolta di oggetti diversi. È quindi possibile utilizzare ArrayList allo stesso modo con cui si utilizza una matrice. Anziché creare un campo che restituisca una matrice di oggetti tipizzati, è tuttavia possibile creare un campo che restituisca un solo ArrayList. Tuttavia, così come avviene con le matrici, è necessario informare XmlSerializer dei tipi di oggetti contenuti in ArrayList. A tale scopo, assegnare più istanze di XmlElementAttribute al campo, come illustrato nell'esempio riportato di seguito.

Public Class Group
    <XmlElement(Type:=GetType(Employee)), _
    XmlElement(Type:=GetType(Manager))> _
    Public Info As ArrayList
End Class
public class Group {
    [XmlElement(Type = typeof(Employee)),
    XmlElement(Type = typeof(Manager))]
    public ArrayList Info;
}

Controllo della serializzazione di classi tramite XmlRootAttribute e XmlTypeAttribute

A una classe è possibile applicare solo due attributi: XmlRootAttribute e XmlTypeAttribute. Questi attributi sono simili. XmlRootAttribute può essere applicato a una sola classe, ovvero alla classe che, se serializzata, rappresenta l'elemento di apertura e chiusura del documento XML, in altre parole, l'elemento principale. XmlTypeAttribute, invece, può essere applicato a qualsiasi classe, inclusa la classe radice.

Ad esempio, negli esempi precedenti, la classe Group è la classe radice e tutte le sue proprietà e i campi pubblici diventano gli elementi XML trovati nel documento XML. Pertanto, è possibile avere una sola classe radice. Tramite l'applicazione di XmlRootAttribute, è possibile controllare il flusso XML generato da XmlSerializer. Ad esempio, è possibile modificare il nome dell'elemento e lo spazio dei nomi.

XmlTypeAttribute consente di controllare lo schema dell'XML generato. Questa funzionalità risulta utile quando è necessario pubblicare lo schema tramite un servizio Web XML. Nell'esempio riportato di seguito, applica entrambi XmlTypeAttribute e XmlRootAttribute alla stessa classe:

<XmlRoot("NewGroupName"), _
XmlType("NewTypeName")> _
Public Class Group
    Public Employees() As Employee
End Class
[XmlRoot("NewGroupName")]
[XmlType("NewTypeName")]
public class Group {
    public Employee[] Employees;
}

Se questa classe è compilata e viene utilizzato lo strumento XML Schema Definition per generare lo schema, si trova il seguente XML con la descrizione di Group:

<xs:element name="NewGroupName" type="NewTypeName" />

Al contrario, se si fosse dovuta serializzare un'istanza della classe, nel documento XML si sarebbe trovato solo NewGroupName:

<NewGroupName>
    . . .
</NewGroupName>

Come impedire la serializzazione con XmlIgnoreAttribute

Potrebbe verificarsi una situazione in cui non è necessario serializzare una proprietà o un campo pubblici. Ad esempio, un campo o una proprietà possono essere utilizzati per contenere metadati. In tali casi, applicare XmlIgnoreAttribute al campo o alla proprietà e XmlSerializer permetterà di ignorarli.

Vedi anche