Delen via


Verzamelingstypen in gegevenscontracten

Een verzameling is een lijst met items van een bepaald type. In .NET Framework kunnen dergelijke lijsten worden weergegeven met behulp van matrices of een verscheidenheid aan andere typen (algemene lijst, algemeen BindingList<T>of StringCollectionArrayList). Een verzameling kan bijvoorbeeld een lijst met adressen voor een bepaalde klant bevatten. Deze verzamelingen worden lijstverzamelingen genoemd, ongeacht het werkelijke type.

Er bestaat een speciale vorm van verzameling die een koppeling vertegenwoordigt tussen het ene item (de 'sleutel') en een andere (de 'waarde'). In .NET Framework worden deze vertegenwoordigd door typen zoals Hashtable en de algemene woordenlijst. Een koppelingsverzameling kan bijvoorbeeld een plaats ('sleutel') toewijzen aan de populatie ('waarde'). Deze verzamelingen worden woordenlijstverzamelingen genoemd, ongeacht het werkelijke type.

Verzamelingen krijgen een speciale behandeling in het gegevenscontractmodel.

Typen die de IEnumerable interface implementeren, inclusief matrices en algemene verzamelingen, worden herkend als verzamelingen. Van deze typen zijn typen die de IDictionary of algemene IDictionary<TKey,TValue> interfaces implementeren woordenlijstverzamelingen; alle andere zijn lijstverzamelingen.

Aanvullende vereisten voor verzamelingstypen, zoals het hebben van een methode die wordt aangeroepen Add en een constructor zonder parameters, worden in de volgende secties uitgebreid besproken. Dit zorgt ervoor dat verzamelingstypen zowel geserialiseerd als gedeserialiseerd kunnen worden. Dit betekent dat sommige verzamelingen niet rechtstreeks worden ondersteund, zoals de Algemene ReadOnlyCollection<T> verzameling (omdat deze geen constructor zonder parameters heeft). Zie de sectie 'Verzamelingsinterfacetypen en alleen-lezenverzamelingen gebruiken' verderop in dit onderwerp voor informatie over het omzeilen van deze beperkingen.

De typen in verzamelingen moeten gegevenscontracttypen zijn of anderszins serialiseerbaar zijn. Zie Typen die worden ondersteund door de Serializer van het gegevenscontract voor meer informatie.

Zie de informatie over het serialiseren van verzamelingen in de sectie Geavanceerde verzamelingsregels van dit onderwerp voor meer informatie over wat en wat niet als een geldige verzameling wordt beschouwd, en over hoe verzamelingen worden geserialiseerd.

Verwisselbare verzamelingen

Alle lijstverzamelingen van hetzelfde type worden beschouwd als hetzelfde gegevenscontract (tenzij ze worden aangepast met behulp van het CollectionDataContractAttribute kenmerk, zoals verderop in dit onderwerp wordt besproken). De volgende gegevenscontracten zijn dus gelijkwaardig.

[DataContract(Name = "PurchaseOrder")]
public class PurchaseOrder1
{
    [DataMember]
    public string customerName;
    [DataMember]
    public Collection<Item> items;
    [DataMember]
    public string[] comments;
}

[DataContract(Name = "PurchaseOrder")]
public class PurchaseOrder2
{
    [DataMember]
    public string customerName;
    [DataMember]
    public List<Item> items;
    [DataMember]
    public BindingList<string> comments;
}
<DataContract(Name:="PurchaseOrder")>
Public Class PurchaseOrder1

    <DataMember()>
    Public customerName As String

    <DataMember()>
    Public items As Collection(Of Item)

    <DataMember()>
    Public comments() As String

End Class

<DataContract(Name:="PurchaseOrder")>
Public Class PurchaseOrder2

    <DataMember()>
    Public customerName As String

    <DataMember()>
    Public items As List(Of Item)

    <DataMember()>
    Public comments As BindingList(Of String)

End Class

Beide gegevenscontracten resulteren in XML die vergelijkbaar is met de volgende code.

<PurchaseOrder>
    <customerName>...</customerName>
    <items>
        <Item>...</Item>
        <Item>...</Item>
        <Item>...</Item>
        ...
    </items>
    <comments>
        <string>...</string>
        <string>...</string>
        <string>...</string>
        ...
    </comments>
</PurchaseOrder>

Doorwisselbaarheid van verzamelingen kunt u bijvoorbeeld een verzamelingstype gebruiken dat is geoptimaliseerd voor prestaties op de server en een verzamelingstype dat is ontworpen om te worden gebonden aan onderdelen van de gebruikersinterface op de client.

Net als bij lijstverzamelingen worden alle woordenlijstverzamelingen met dezelfde sleutel- en waardetypen beschouwd als hetzelfde gegevenscontract (tenzij aangepast door het CollectionDataContractAttribute kenmerk).

Alleen het gegevenscontracttype is van belang wat betreft de gelijkwaardigheid van verzamelingen, niet .NET-typen. Dat wil gezegd, een verzameling van Type1 wordt beschouwd als gelijkwaardig aan een verzameling van Type2 als Type1 en Type2 gelijkwaardige gegevenscontracten hebben.

Niet-algemene verzamelingen worden beschouwd als hetzelfde gegevenscontract als algemene verzamelingen van het type Object. (De gegevenscontracten voor ArrayList en Algemeen List<T>Object zijn bijvoorbeeld hetzelfde.)

Verzamelingsinterfacetypen en alleen-lezenverzamelingen gebruiken

Verzamelingsinterfacetypen (IEnumerablealgemene IDictionary, algemene IDictionary<TKey,TValue>of interfaces die zijn afgeleid van deze interfaces) worden ook beschouwd als verzamelingsgegevenscontracten, vergelijkbaar met het verzamelen van gegevenscontracten voor werkelijke verzamelingstypen. Het is dus mogelijk om het type te declareren dat wordt geserialiseerd als een type verzamelingsinterface en de resultaten hetzelfde zijn als als een werkelijk verzamelingstype is gebruikt. De volgende gegevenscontracten zijn bijvoorbeeld gelijkwaardig.

[DataContract(Name="Customer")]
public class Customer1
{
    [DataMember]
    public string customerName;
    [DataMember]
    public Collection<Address> addresses;
}

[DataContract(Name="Customer")]
public class Customer2
{
    [DataMember]
    public string customerName;
    [DataMember]
    public ICollection<Address> addresses;
}
<DataContract(Name:="Customer")>
Public Class Customer1

    <DataMember()>
    Public customerName As String

    <DataMember()>
    Public addresses As Collection(Of Address)

End Class

<DataContract(Name:="Customer")>
Public Class Customer2

    <DataMember()>
    Public customerName As String

    <DataMember()>
    Public addresses As ICollection(Of Address)

End Class

Wanneer het gedeclareerde type tijdens de serialisatie een interface is, kan het gebruikte exemplaartype elk type zijn dat die interface implementeert. Beperkingen die eerder zijn besproken (met een constructor zonder parameters en een Add methode) zijn niet van toepassing. U kunt bijvoorbeeld adressen in Customer2 instellen op een exemplaar van Algemeen ReadOnlyCollection<T> adres, ook al kunt u geen gegevenslid van het type Algemeen ReadOnlyCollection<T>rechtstreeks declareren.

Wanneer het gedeserialiseerde type een interface is, kiest de serialisatie-engine een type dat de gedeclareerde interface implementeert en het type wordt geïnstantieerd. Het mechanisme voor bekende typen (beschreven in bekende gegevenscontracttypen) heeft hier geen effect. De keuze van het type is ingebouwd in WCF.

Verzamelingstypen aanpassen

U kunt verzamelingstypen aanpassen met behulp van het CollectionDataContractAttribute kenmerk, dat verschillende toepassingen heeft.

Houd er rekening mee dat het aanpassen van verzamelingstypen inbreuk maakt op de uitwisselbaarheid van verzamelingen, dus het wordt over het algemeen aanbevolen om te voorkomen dat dit kenmerk waar mogelijk wordt toegepast. Zie de sectie Geavanceerde verzamelingsregels verderop in dit onderwerp voor meer informatie over dit probleem.

Naamgeving van gegevenscontract verzamelen

De regels voor naamverzamelingstypen zijn vergelijkbaar met die voor het benoemen van reguliere gegevenscontracttypen, zoals beschreven in namen van gegevenscontractnamen, hoewel er enkele belangrijke verschillen zijn:

  • Het CollectionDataContractAttribute kenmerk wordt gebruikt om de naam aan te passen in plaats van het DataContractAttribute kenmerk. Het CollectionDataContractAttribute kenmerk heeft Name ook eigenschappen en Namespace eigenschappen.

  • Wanneer het CollectionDataContractAttribute kenmerk niet wordt toegepast, zijn de standaardnaam en naamruimte voor verzamelingstypen afhankelijk van de namen en naamruimten van typen in de verzameling. Ze worden niet beïnvloed door de naam en naamruimte van het verzamelingstype zelf. Zie de volgende typen voor een voorbeeld.

    public CustomerList1 : Collection<string> {}
    public StringList1 : Collection<string> {}
    

De naam van beide typen gegevenscontract is 'ArrayOfstring' en niet 'CustomerList1' of 'StringList1'. Dit betekent dat het serialiseren van een van deze typen op het hoofdniveau XML oplevert die vergelijkbaar is met de volgende code.

<ArrayOfstring>
    <string>...</string>
    <string>...</string>
    <string>...</string>
    ...
</ArrayOfstring>

Deze naamgevingsregel is gekozen om ervoor te zorgen dat elk niet-aangepast type dat een lijst met tekenreeksen vertegenwoordigt, hetzelfde gegevenscontract en dezelfde XML-weergave heeft. Dit maakt de uitwisselbaarheid van verzamelingen mogelijk. In dit voorbeeld zijn CustomerList1 en StringList1 volledig uitwisselbaar.

Wanneer het CollectionDataContractAttribute kenmerk echter wordt toegepast, wordt de verzameling een aangepast gegevenscontract voor verzamelingen, zelfs als er geen eigenschappen zijn ingesteld op het kenmerk. De naam en naamruimte van het gegevenscontract voor verzameling zijn vervolgens afhankelijk van het verzamelingstype zelf. Zie het volgende type voor een voorbeeld.

[CollectionDataContract]
public class CustomerList2 : Collection<string> {}
<CollectionDataContract()>
Public Class CustomerList2
    Inherits Collection(Of String)
End Class

Wanneer deze is geserialiseerd, is de resulterende XML vergelijkbaar met het volgende.

<CustomerList2>
    <string>...</string>
    <string>...</string>
    <string>...</string>
    ...
</CustomerList2>

U ziet dat dit niet langer gelijk is aan de XML-weergave van de niet-aangepaste typen.

  • U kunt de Name en Namespace eigenschappen gebruiken om de naamgeving verder aan te passen. Zie de volgende klasse.

    [CollectionDataContract(Name="cust_list")]
    public class CustomerList3 : Collection<string> {}
    
    <CollectionDataContract(Name:="cust_list")>
    Public Class CustomerList3
        Inherits Collection(Of String)
    End Class
    

De resulterende XML is vergelijkbaar met het volgende.

<cust_list>
    <string>...</string>
    <string>...</string>
    <string>...</string>
    ...
</cust_list>

Zie de sectie Geavanceerde verzamelingsregels verderop in dit onderwerp voor meer informatie.

De naam van het herhalende element in lijstverzamelingen aanpassen

Lijstverzamelingen bevatten herhalende vermeldingen. Normaal gesproken wordt elke herhalende vermelding weergegeven als een element met de naam van het gegevenscontract van het type in de verzameling.

In de CustomerList voorbeelden bevatten de verzamelingen tekenreeksen. De naam van het gegevenscontract voor het primitieve tekenreekstype is 'tekenreeks', dus het herhalende element was '<tekenreeks>'.

Met behulp van de ItemName eigenschap op het CollectionDataContractAttribute kenmerk kan deze herhalende elementnaam echter worden aangepast. Zie het volgende type voor een voorbeeld.

[CollectionDataContract(ItemName="customer")]
public class CustomerList4 : Collection<string>  {}
<CollectionDataContract(ItemName:="customer")>
Public Class CustomerList4
    Inherits Collection(Of String)
End Class

De resulterende XML is vergelijkbaar met het volgende.

<CustomerList4>
    <customer>...</customer>
    <customer>...</customer>
    <customer>...</customer>
    ...
</CustomerList4>

De naamruimte van het herhalende element is altijd hetzelfde als de naamruimte van het gegevenscontract voor verzameling, die kan worden aangepast met behulp van de Namespace eigenschap, zoals eerder beschreven.

Woordenlijstverzamelingen aanpassen

Woordenlijstverzamelingen zijn in wezen lijsten met vermeldingen, waarbij elke vermelding een sleutel heeft gevolgd door een waarde. Net als bij gewone lijsten kunt u de elementnaam wijzigen die overeenkomt met het herhalende element met behulp van de ItemName eigenschap.

Daarnaast kunt u de elementnamen wijzigen die de sleutel en de waarde vertegenwoordigen met behulp van de KeyName en ValueName eigenschappen. De naamruimten voor deze elementen zijn hetzelfde als de naamruimte van het gegevenscontract voor verzameling.

Zie het volgende type voor een voorbeeld.

[CollectionDataContract
    (Name = "CountriesOrRegionsWithCapitals",
    ItemName = "entry",
    KeyName = "countryorregion",
    ValueName = "capital")]
public class CountriesOrRegionsWithCapitals2 : Dictionary<string, string> { }
<CollectionDataContract(Name:="CountriesOrRegionsWithCapitals",
                        ItemName:="entry", KeyName:="countryorregion",
                        ValueName:="capital")>
Public Class CountriesOrRegionsWithCapitals2
    Inherits Dictionary(Of String, String)
End Class

Wanneer deze is geserialiseerd, is de resulterende XML vergelijkbaar met het volgende.

<CountriesOrRegionsWithCapitals>
    <entry>
        <countryorregion>USA</countryorregion>
        <capital>Washington</capital>
    </entry>
    <entry>
        <countryorregion>France</countryorregion>
        <capital>Paris</capital>
    </entry>
    ...
</CountriesOrRegionsWithCapitals>

Zie de sectie Geavanceerde verzamelingsregels verderop in dit onderwerp voor meer informatie over woordenlijstverzamelingen.

Verzamelingen en bekende typen

U hoeft geen verzamelingstypen toe te voegen aan bekende typen wanneer u polymorf wordt gebruikt in plaats van andere verzamelingen of verzamelingsinterfaces. Als u bijvoorbeeld een gegevenslid van het type IEnumerable declareert en dit gebruikt om een exemplaar ArrayListte verzenden, hoeft u niet toe te voegen ArrayList aan bekende typen.

Wanneer u verzamelingen polymorf gebruikt in plaats van niet-verzamelingstypen, moeten ze worden toegevoegd aan bekende typen. Als u bijvoorbeeld een gegevenslid van het type Object declareert en dit gebruikt om een exemplaar te ArrayListverzenden, voegt u dit toe ArrayList aan bekende typen.

Hiermee kunt u geen equivalente verzameling polymorf serialiseren. Wanneer u bijvoorbeeld toevoegt ArrayList aan de lijst met bekende typen in het vorige voorbeeld, kunt u de Array of Object klasse niet toewijzen, ook al heeft het een gelijkwaardig gegevenscontract. Dit verschilt niet van het normale gedrag van bekende typen voor serialisatie voor niet-verzamelingstypen, maar het is vooral belangrijk om te begrijpen in het geval van verzamelingen, omdat het zeer gebruikelijk is dat verzamelingen gelijkwaardig zijn.

Tijdens de serialisatie kan slechts één type bekend zijn in een bepaald bereik voor een bepaald gegevenscontract en equivalente verzamelingen hebben allemaal dezelfde gegevenscontracten. Dit betekent dat u in het vorige voorbeeld niet zowel ArrayList als Array of Object aan bekende typen in hetzelfde bereik kunt toevoegen. Nogmaals, dit is gelijk aan bekend typegedrag voor niet-verzamelingstypen, maar het is vooral belangrijk om te begrijpen voor verzamelingen.

Bekende typen zijn mogelijk ook vereist voor de inhoud van verzamelingen. Als een ArrayList exemplaar bijvoorbeeld daadwerkelijk exemplaren Type1 van en Type2bevat, moeten beide typen worden toegevoegd aan bekende typen.

In het volgende voorbeeld ziet u een correct samengestelde objectgrafiek met behulp van verzamelingen en bekende typen. Het voorbeeld is enigszins vervormd, omdat u in een werkelijke toepassing normaal gesproken niet de volgende gegevensleden zou definiëren als Object, en dus geen bekende type-/polymorfismeproblemen hebben.

[DataContract]
public class Employee
{
    [DataMember]
    public string name = "John Doe";
    [DataMember]
    public Payroll payrollRecord;
    [DataMember]
    public Training trainingRecord;
}

[DataContract]
[KnownType(typeof(int[]))] //required because int[] is used polymorphically
[KnownType(typeof(ArrayList))] //required because ArrayList is used polymorphically
public class Payroll
{
    [DataMember]
    public object salaryPayments = new int[12];
    //float[] not needed in known types because polymorphic assignment is to another collection type
    [DataMember]
    public IEnumerable<float> stockAwards = new float[12];
    [DataMember]
    public object otherPayments = new ArrayList();
}

[DataContract]
[KnownType(typeof(List<object>))]
//required because List<object> is used polymorphically
//does not conflict with ArrayList above because it's a different scope,
//even though it's the same data contract
[KnownType(typeof(InHouseTraining))] //Required if InHouseTraining can be used in the collection
[KnownType(typeof(OutsideTraining))] //Required if OutsideTraining can be used in the collection
public class Training
{
    [DataMember]
    public object training = new List<object>();
}

[DataContract]
public class InHouseTraining
{
    //code omitted
}

[DataContract]
public class OutsideTraining
{
    //code omitted
}
<DataContract()>
Public Class Employee

    <DataMember()>
    Public name As String = "John Doe"

    <DataMember()>
    Public payrollRecord As Payroll

    <DataMember()>
    Public trainingRecord As Training

End Class

<DataContract(), KnownType(GetType(Integer())), KnownType(GetType(ArrayList))>
Public Class Payroll

    <DataMember()>
    Public salaryPayments As Object = New Integer(11) {}

    'float[] not needed in known types because polymorphic assignment is to another collection type
    <DataMember()>
    Public stockAwards As IEnumerable(Of Single) = New Single(11) {}

    <DataMember()>
    Public otherPayments As Object = New ArrayList()

End Class

'required because List<object> is used polymorphically
'does not conflict with ArrayList above because it's a different scope, 
'even though it's the same data contract
<DataContract(), KnownType(GetType(List(Of Object))),
                 KnownType(GetType(InHouseTraining)),
                 KnownType(GetType(OutsideTraining))>
Public Class Training
    <DataMember()>
    Public training As Object = New List(Of Object)()
End Class

<DataContract()>
Public Class InHouseTraining
    'code omitted…
End Class

<DataContract()>
Public Class OutsideTraining
    'code omitted…
End Class

Als het gedeserialiseerde type een verzamelingstype is, wordt het gedeclareerde type geïnstantieerd, ongeacht het type dat daadwerkelijk is verzonden. Als het gedeclareerde type een verzamelingsinterface is, kiest de deserializer een type dat moet worden geïnstantieerd zonder rekening te houden met bekende typen.

Als het gedeserialiseerde type geen verzamelingstype is, maar een verzamelingstype wordt verzonden, wordt een overeenkomend verzamelingstype uit de lijst met bekende typen gekozen. Het is mogelijk om verzamelingsinterfacetypen toe te voegen aan de lijst met bekende typen voor deserialisatie. In dit geval kiest de deserialisatie-engine opnieuw een type dat moet worden geïnstantieerd.

Verzamelingen en de Klasse NetDataContractSerializer

Wanneer de NetDataContractSerializer klasse in gebruik is, verliezen niet-aangepaste verzamelingstypen (zonder het CollectionDataContractAttribute kenmerk) die geen matrices zijn hun speciale betekenis.

Niet-aangepaste verzamelingstypen die zijn gemarkeerd met het SerializableAttribute kenmerk, kunnen nog steeds worden geserialiseerd door de NetDataContractSerializer klasse volgens het SerializableAttribute kenmerk of de ISerializable interfaceregels.

Aangepaste verzamelingstypen, verzamelingsinterfaces en matrices worden nog steeds behandeld als verzamelingen, zelfs wanneer de NetDataContractSerializer klasse wordt gebruikt.

Verzamelingen en schema's

Alle equivalente verzamelingen hebben dezelfde weergave in het XSD-schema (XML Schema Definition Language). Daarom krijgt u normaal gesproken niet hetzelfde verzamelingstype in de gegenereerde clientcode als de code op de server. De server kan bijvoorbeeld een gegevenscontract met een algemeen List<T> geheel getal-lid gebruiken, maar in de gegenereerde clientcode kan hetzelfde gegevenslid een matrix met gehele getallen worden.

Woordenboekverzamelingen zijn gemarkeerd met een WCF-specifieke schemaaantekening die aangeeft dat het woordenlijsten zijn; anders zijn ze niet te onderscheiden van eenvoudige lijsten die vermeldingen met een sleutel en een waarde bevatten. Zie Data Contract Schema Reference voor een exacte beschrijving van hoe verzamelingen worden weergegeven in het gegevenscontractschema.

Standaard worden typen niet gegenereerd voor niet-aangepaste verzamelingen in geïmporteerde code. Gegevensleden van lijstverzamelingstypen worden geïmporteerd als matrices en gegevensleden van typen woordenlijstverzameling worden geïmporteerd als Algemene woordenlijst.

Voor aangepaste verzamelingen worden echter afzonderlijke typen gegenereerd, gemarkeerd met het CollectionDataContractAttribute kenmerk. (Een aangepast verzamelingstype in het schema is een type dat geen gebruik maakt van de standaardnaamruimte, naam, herhalende elementnaam of namen van sleutel-/waarde-elementen.) Deze typen zijn lege typen die zijn afgeleid van Algemeen List<T> voor lijsttypen en Algemene woordenlijst voor woordenlijsttypen.

U hebt bijvoorbeeld de volgende typen op de server.

[DataContract]
public class CountryOrRegion
{
    [DataMember]
    public Collection<string> officialLanguages;
    [DataMember]
    public List<DateTime> holidays;
    [DataMember]
    public CityList cities;
    [DataMember]
    public ArrayList otherInfo;
}

public class Person
{
    public Person(string fName, string lName)
    {
        this.firstName = fName;
        this.lastName = lName;
    }

    public string firstName;
    public string lastName;
}

public class PeopleEnum : IEnumerator
{
    public Person[] _people;

    // Enumerators are positioned before the first element
    // until the first MoveNext() call.
    int position = -1;

    public PeopleEnum(Person[] list)
    {
        _people = list;
    }

    public bool MoveNext()
    {
        position++;
        return (position < _people.Length);
    }

    public void Reset()
    {
        position = -1;
    }

    public object Current
    {
        get
        {
            try
            {
                return _people[position];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }
}

[CollectionDataContract(Name = "Cities", ItemName = "city", KeyName = "cityName", ValueName = "population")]
public class CityList : IDictionary<string, int>, IEnumerable<System.Collections.Generic.KeyValuePair<string, int>>
{
    private Person[] _people = null;

    public bool ContainsKey(string s) { return true; }
    public bool Contains(string s) { return true; }
    public bool Contains(KeyValuePair<string, int> item) { return (true); }
    public void Add(string key, int value) { }
    public void Add(KeyValuePair<string, int> keykValue) { }
    public bool Remove(string s) { return true; }
    public bool TryGetValue(string d, out int i)
    {
        i = 0; return (true);
    }

    /*
    [TypeConverterAttribute(typeof(SynchronizationHandlesTypeConverter))]
    public ICollection<string> SynchronizationHandles {
        get { return (System.Collections.Generic.ICollection<string>) new Stack<string> (); }
        set { }
    }*/

    public ICollection<string> Keys
    {
        get
        {
            return (System.Collections.Generic.ICollection<string>)new Stack<string>();
        }
    }

    public int this[string s]
    {
        get
        {
            return 0;
        }
        set
        {
        }
    }

    public ICollection<int> Values
    {
        get
        {
            return (System.Collections.Generic.ICollection<int>)new Stack<string>();
        }
    }

    public void Clear() { }
    public void CopyTo(KeyValuePair<string, int>[] array, int index) { }
    public bool Remove(KeyValuePair<string, int> item) { return true; }
    public int Count { get { return 0; } }
    public bool IsReadOnly { get { return true; } }

    IEnumerator<KeyValuePair<string, int>>
        System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, int>>.GetEnumerator()
    {
        return (IEnumerator<KeyValuePair<string, int>>)new PeopleEnum(_people); ;
    }

    public IEnumerator GetEnumerator()
    {
        return new PeopleEnum(_people);
    }
}

<DataContract()>
Public Class CountryOrRegion

    <DataMember()>
    Public officialLanguages As Collection(Of String)

    <DataMember()>
    Public holidays As List(Of DateTime)

    <DataMember()>
    Public cities As CityList

    <DataMember()>
    Public otherInfo As ArrayList

End Class

Public Class Person
    Public Sub New(ByVal fName As String, ByVal lName As String)
        Me.firstName = fName
        Me.lastName = lName
    End Sub

    Public firstName As String
    Public lastName As String
End Class

Public Class PeopleEnum
    Implements IEnumerator

    Public _people() As Person
    ' Enumerators are positioned before the first element
    ' until the first MoveNext() call.
    Private position As Integer = -1

    Public Sub New(ByVal list() As Person)
        _people = list
    End Sub

    Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
        position += 1
        Return position < _people.Length
    End Function

    Public Sub Reset() Implements IEnumerator.Reset
        position = -1
    End Sub

    Public ReadOnly Property Current() As Object Implements IEnumerator.Current
        Get
            Try
                Return _people(position)
            Catch e1 As IndexOutOfRangeException
                Throw New InvalidOperationException()
            End Try
        End Get
    End Property
End Class

<CollectionDataContract(Name:="Cities",
                        ItemName:="city",
                        KeyName:="cityName",
                        ValueName:="population")>
Public Class CityList
    Implements IDictionary(Of String, Integer), IEnumerable(Of System.Collections.Generic.KeyValuePair(Of String, Integer))

    Private _people() As Person = Nothing

    Public Function ContainsKey(ByVal s As String) As Boolean Implements IDictionary(Of String, Integer).ContainsKey
        Return True
    End Function

    Public Function Contains(ByVal s As String) As Boolean
        Return True
    End Function

    Public Function Contains(ByVal item As KeyValuePair(Of String, Integer)) As Boolean Implements IDictionary(Of String, Integer).Contains
        Return (True)
    End Function

    Public Sub Add(ByVal key As String,
                   ByVal value As Integer) Implements IDictionary(Of String, Integer).Add
    End Sub

    Public Sub Add(ByVal keykValue As KeyValuePair(Of String, Integer)) Implements IDictionary(Of String, Integer).Add
    End Sub

    Public Function Remove(ByVal s As String) As Boolean Implements IDictionary(Of String, Integer).Remove
        Return True
    End Function

    Public Function TryGetValue(ByVal d As String,
                                <System.Runtime.InteropServices.Out()> ByRef i As Integer) _
                                As Boolean Implements IDictionary(Of String, Integer).TryGetValue
        i = 0
        Return (True)
    End Function

    Public ReadOnly Property Keys() As ICollection(Of String) Implements IDictionary(Of String, Integer).Keys
        Get
            Return CType(New Stack(Of String)(), System.Collections.Generic.ICollection(Of String))
        End Get
    End Property

    Default Public Property Item(ByVal s As String) As Integer Implements IDictionary(Of String, Integer).Item
        Get
            Return 0
        End Get
        Set(ByVal value As Integer)
        End Set
    End Property

    Public ReadOnly Property Values() As ICollection(Of Integer) Implements IDictionary(Of String, Integer).Values
        Get
            Return CType(New Stack(Of String)(), System.Collections.Generic.ICollection(Of Integer))
        End Get
    End Property

    Public Sub Clear() Implements IDictionary(Of String, Integer).Clear
    End Sub

    Public Sub CopyTo(ByVal array() As KeyValuePair(Of String, Integer),
                      ByVal index As Integer) Implements IDictionary(Of String, Integer).CopyTo
    End Sub

    Public Function Remove(ByVal item As KeyValuePair(Of String, Integer)) As Boolean Implements IDictionary(Of String, Integer).Remove
        Return True
    End Function

    Public ReadOnly Property Count() As Integer Implements IDictionary(Of String, Integer).Count
        Get
            Return 0
        End Get
    End Property

    Public ReadOnly Property IsReadOnly() As Boolean Implements IDictionary(Of String, Integer).IsReadOnly
        Get
            Return True
        End Get
    End Property

    Private Function IEnumerable_GetEnumerator() As IEnumerator(Of KeyValuePair(Of String, Integer)) _
        Implements System.Collections.Generic.IEnumerable(Of System.Collections.Generic.KeyValuePair(Of String, Integer)).GetEnumerator

        Return CType(New PeopleEnum(_people), IEnumerator(Of KeyValuePair(Of String, Integer)))
    End Function

    Public Function GetEnumerator() As IEnumerator Implements System.Collections.IEnumerable.GetEnumerator

        Return New PeopleEnum(_people)

    End Function

End Class

Wanneer het schema wordt geëxporteerd en opnieuw wordt geïmporteerd, is de gegenereerde clientcode vergelijkbaar met het volgende (velden worden weergegeven in plaats van eigenschappen om het lezen te vereenvoudigen).

[DataContract]
public class CountryOrRegion2
{
    [DataMember]
    public string[] officialLanguages;
    [DataMember]
    public DateTime[] holidays;
    [DataMember]
    public Cities cities;
    [DataMember]
    public object[] otherInfo;
}

[CollectionDataContract(ItemName = "city", KeyName = "cityName", ValueName = "population")]
public class Cities : Dictionary<string, int> { }
<DataContract()>
Public Class CountryOrRegion2
    <DataMember()>
    Public officialLanguages() As String
    <DataMember()>
    Public holidays() As DateTime
    <DataMember()>
    Public cities As Cities
    <DataMember()>
    Public otherInfo() As Object
End Class

<CollectionDataContract(ItemName:="city", KeyName:="cityName", ValueName:="population")>
Public Class Cities
    Inherits Dictionary(Of String, Integer)
End Class

Mogelijk wilt u verschillende typen in gegenereerde code gebruiken dan de standaardtypen. U kunt bijvoorbeeld Generic BindingList<T> gebruiken in plaats van gewone matrices voor uw gegevensleden om ze gemakkelijker te binden aan onderdelen van de gebruikersinterface.

Als u verzamelingstypen wilt kiezen die u wilt genereren, geeft u een lijst met verzamelingstypen door die u wilt gebruiken in de ReferencedCollectionTypes eigenschap van het object bij het ImportOptions importeren van het schema. Deze typen worden verzamelingstypen waarnaar wordt verwezen genoemd.

Wanneer naar algemene typen wordt verwezen, moeten ze volledig geopende generieken of volledig gesloten generieken zijn.

Notitie

Wanneer u het hulpprogramma Svcutil.exe gebruikt, kan deze verwijzing worden uitgevoerd met behulp van de opdrachtregelswitch /collectionType (korte vorm: /ct). Houd er rekening mee dat u ook de assembly moet opgeven voor de typen verzameling waarnaar wordt verwezen met behulp van de /reference-switch (korte vorm: /r). Als het type algemeen is, moet het worden gevolgd door een aanhalingsteken en het aantal algemene parameters. De aanhalingsteken (') moet niet worden verward met het enkele aanhalingsteken (') . U kunt meerdere typen verzamelingen waarnaar wordt verwezen opgeven met behulp van de schakeloptie /collectionType meerdere keren.

Als u bijvoorbeeld wilt dat alle lijsten worden geïmporteerd als Algemeen List<T>.

svcutil.exe MyService.wsdl MyServiceSchema.xsd /r:C:\full_path_to_system_dll\System.dll /ct:System.Collections.Generic.List`1

Wanneer u een verzameling importeert, wordt deze lijst met verzamelingstypen waarnaar wordt verwezen gescand en wordt de best overeenkomende verzameling gebruikt als deze wordt gevonden, hetzij als gegevenslidtype (voor niet-aangepaste verzamelingen) of als basistype waaruit moet worden afgeleid (voor aangepaste verzamelingen). Woordenlijsten worden alleen vergeleken met woordenlijsten, terwijl lijsten worden vergeleken met lijsten.

Als u bijvoorbeeld de algemene BindingList<T> code en Hashtable de lijst met typen waarnaar wordt verwezen toevoegt, is de gegenereerde clientcode voor het voorgaande voorbeeld vergelijkbaar met het volgende.

[DataContract]
public class CountryOrRegion3
{
    [DataMember]
    public BindingList<string> officialLanguages;
    [DataMember]
    public BindingList<DateTime> holidays;
    [DataMember]
    public Cities cities;
    [DataMember]
    public BindingList<object> otherInfo;
}

[CollectionDataContract(ItemName = "city", KeyName = "cityName", ValueName = "population")]
public class Cities3 : Hashtable { }
<DataContract()>
Public Class CountryOrRegion3

    <DataMember()>
    Public officialLanguages As BindingList(Of String)

    <DataMember()>
    Public holidays As BindingList(Of DateTime)

    <DataMember()>
    Public cities As Cities

    <DataMember()>
    Public otherInfo As BindingList(Of Object)

End Class

<CollectionDataContract(ItemName:="city",
                        KeyName:="cityName",
                        ValueName:="population")>
Public Class Cities3
    Inherits Hashtable
End Class

U kunt typen verzamelingsinterfaces opgeven als onderdeel van uw verzamelingstypen waarnaar wordt verwezen, maar u kunt geen ongeldige verzamelingstypen opgeven (zoals typen zonder Add methode of openbare constructor).

Een gesloten algemeen wordt beschouwd als de beste overeenkomst. (Niet-generieke typen worden beschouwd als gelijkwaardig aan gesloten generieken van Object). Als bijvoorbeeld de typen Algemeen List<T> van, Algemeen BindingList<T> (open algemeen) zijn en ArrayList de verzamelingstypen waarnaar wordt verwezen, wordt DateTimehet volgende gegenereerd.

[DataContract]
public class CountryOrRegion4
{
    [DataMember]
    public string[] officialLanguages;
    [DataMember]
    public DateTime[] holidays;
    [DataMember]
    public Cities cities;
    [DataMember]
    public object[] otherInfo;
}

[CollectionDataContract(ItemName = "city", KeyName = "cityName", ValueName = "population")]
public class Cities4 : Dictionary<string, int> { }
<DataContract()>
Public Class CountryOrRegion4

    <DataMember()>
    Public officialLanguages() As String

    <DataMember()>
    Public holidays() As DateTime

    <DataMember()>
    Public cities As Cities

    <DataMember()>
    Public otherInfo() As Object

End Class

<CollectionDataContract(ItemName:="city",
                        KeyName:="cityName",
                        ValueName:="population")>
Public Class Cities4
    Inherits Dictionary(Of String, Integer)
End Class

Voor lijstverzamelingen worden alleen de gevallen in de volgende tabel ondersteund.

Type waarnaar wordt verwezen Interface geïmplementeerd op type waarnaar wordt verwezen Opmerking Type behandeld als:
Niet-algemeen of gesloten algemeen (een willekeurig aantal parameters) Niet-algemeen MyType : IList

or

MyType<T> : IList

waarbij T= int
Gesloten algemeen van Object (bijvoorbeeld IList<object>)
Niet-algemeen of gesloten algemeen (een willekeurig aantal parameters dat niet noodzakelijkerwijs overeenkomt met het verzamelingstype) Gesloten algemeen MyType : IList<string>

or

MyType<T> : IList<string> waarbij T=int
Gesloten algemeen (bijvoorbeeld IList<string>)
Algemeen gesloten met een willekeurig aantal parameters Algemeen openen met een van de parameters van het type MyType<T,U,V> : IList<U>

where T=int, U=string, V=bool
Gesloten algemeen (bijvoorbeeld IList<string>)
Algemeen openen met één parameter Algemeen openen met de parameter van het type MyType<T> : IList<T>, T is geopend Algemeen openen (bijvoorbeeld IList<T>)

Als een type meer dan één interface voor lijstverzameling implementeert, zijn de volgende beperkingen van toepassing:

  • Als het type meerdere keren algemene IEnumerable<T> (of afgeleide interfaces) implementeert voor verschillende typen, wordt het type niet beschouwd als een geldig verzamelingstype waarnaar wordt verwezen en wordt genegeerd. Dit geldt zelfs als sommige implementaties ongeldig zijn of open generics gebruiken. Een type dat Generic IEnumerable<T> of en Generic IEnumerable<T> of int T implementeert, wordt bijvoorbeeld nooit gebruikt als een verzameling int waarnaar wordt verwezen of een ander type, ongeacht of het type een Add methode heeft die een methode accepteert int of een Add methode accepteert die een parameter van het type T accepteert, of beide.

  • Als het type ook een algemene verzamelingsinterface IListimplementeert, wordt het type nooit gebruikt als een verzamelingstype waarnaar wordt verwezen, tenzij de algemene verzamelingsinterface een gesloten algemeen type Objectis.

Voor woordenlijstverzamelingen worden alleen de gevallen in de volgende tabel ondersteund.

Type waarnaar wordt verwezen Interface geïmplementeerd op type waarnaar wordt verwezen Opmerking Type behandeld als
Niet-algemeen of gesloten algemeen (een willekeurig aantal parameters) IDictionary MyType : IDictionary

or

MyType<T> : IDictionary waarbij T=int
Gesloten algemeen IDictionary<object,object>
Gesloten algemeen (een willekeurig aantal parameters) IDictionary<TKey,TValue>Gesloten MyType<T> : IDictionary<string, bool> waarbij T=int Gesloten algemeen (bijvoorbeeld IDictionary<string,bool>)
Gesloten algemeen (een willekeurig aantal parameters) Algemeen IDictionary<TKey,TValue>, een van de sleutel of waarde is gesloten, de andere is geopend en gebruikt een van de parameters van het type MyType<T,U,V> : IDictionary<string,V>where T=, U=intfloat,V=bool

or

MyType<Z> : IDictionary<Z,bool> waarbij Z=string
Gesloten algemeen (bijvoorbeeld IDictionary<string,bool>)
Gesloten algemeen (een willekeurig aantal parameters) Algemeen IDictionary<TKey,TValue>, zowel de sleutel als de waarde zijn geopend en elk gebruikt een van de parameters van het type MyType<T,U,V> : IDictionary<V,U> where T=int, U=bool, V=string Gesloten algemeen (bijvoorbeeld IDictionary<string,bool>)
Algemeen openen (twee parameters) Algemeen IDictionary<TKey,TValue>, open, gebruikt beide algemene parameters van het type in de volgorde waarin ze worden weergegeven MyType<K,V> : IDictionary<K,V>, K en V beide geopend Algemeen openen (bijvoorbeeld IDictionary<K,V>)

Als het type zowel IDictionary als Algemeen implementeert, wordt alleen Algemeen IDictionary<TKey,TValue>IDictionary<TKey,TValue>overwogen.

Het verwijzen naar gedeeltelijke algemene typen wordt niet ondersteund.

Duplicaten zijn bijvoorbeeld niet toegestaan, u kunt niet zowel de algemene List<T> van als de algemene verzameling van IntegerInteger aan ReferencedCollectionTypestoevoegen, omdat dit het onmogelijk maakt om te bepalen welke moet worden gebruikt wanneer een lijst met gehele getallen in het schema wordt gevonden. Duplicaten worden alleen gedetecteerd als er een type in het schema is dat het probleem met duplicaten blootstelt. Als het schema dat wordt geïmporteerd bijvoorbeeld geen lijsten met gehele getallen bevat, mag het zowel de algemene List<T> van Integer als de algemene verzameling Integer in de ReferencedCollectionTypes, maar geen van beide gevolgen hebben.

Geavanceerde verzamelingsregels

Verzamelingen serialiseren

Hier volgt een lijst met verzamelingsregels voor serialisatie:

  • Het combineren van verzamelingstypen (met verzamelingen van verzamelingen) is toegestaan. Onregelmatige matrices worden behandeld als verzamelingen verzamelingen. Multidimensionale matrices worden niet ondersteund.

  • Matrices van byte en matrices zijn XmlNode speciale matrixtypen die worden behandeld als primitieven, niet als verzamelingen. Het serialiseren van een matrix van byte resulteert in één XML-element dat een segment met base64-gecodeerde gegevens bevat, in plaats van een afzonderlijk element voor elke byte. Zie XML- en ADO.NET-typen in gegevenscontracten voor meer informatie over hoe een matrix XmlNode wordt behandeld. Natuurlijk kunnen deze speciale typen zelf deelnemen aan verzamelingen: een matrix van matrix van byte resulteert in meerdere XML-elementen, waarbij elk een segment met Base64-gecodeerde gegevens bevat.

  • Als het DataContractAttribute kenmerk wordt toegepast op een verzamelingstype, wordt het type behandeld als een normaal gegevenscontracttype, niet als een verzameling.

  • Als een verzamelingstype de IXmlSerializable interface implementeert, zijn de volgende regels van toepassing, op basis van een type myType:IList<string>, IXmlSerializable:

    • Als het gedeclareerde type is IList<string>, wordt het type geserialiseerd als een lijst.

    • Als het gedeclareerde type is myType, wordt het geserialiseerd als IXmlSerializable.

    • Als het gedeclareerde type is, wordt IXmlSerializablehet geserialiseerd als IXmlSerializable, maar alleen als u toevoegt myType aan de lijst met bekende typen.

  • Verzamelingen worden geserialiseerd en gedeserialiseerd met behulp van de methoden die worden weergegeven in de volgende tabel.

Verzamelingstype implementeert Methode(en) aangeroepen op serialisatie Methode(en) aangeroepen op deserialisatie
Generieke IDictionary<TKey,TValue> get_Keys, get_Values Algemene toevoegen
IDictionary get_Keys, get_Values Add
Generieke IList<T> Algemene IList<T> indexeerfunctie Algemene toevoegen
Generieke ICollection<T> Enumerator Algemene toevoegen
IList IList Indexer Add
Generieke IEnumerable<T> GetEnumerator Een niet-statische methode Add die één parameter van het juiste type gebruikt (het type algemene parameter of een van de basistypen). Een dergelijke methode moet bestaan voor de serializer om een verzamelingstype te behandelen als een verzameling tijdens zowel serialisatie als deserialisatie.
IEnumerable (en dus ICollection, die daarvan afgeleid is) GetEnumerator Een niet-statische methode die Add één parameter van het type Objectgebruikt. Een dergelijke methode moet bestaan voor de serializer om een verzamelingstype te behandelen als een verzameling tijdens zowel serialisatie als deserialisatie.

De voorgaande tabel bevat verzamelingsinterfaces in aflopende volgorde van prioriteit. Dit betekent bijvoorbeeld dat als een type zowel IList als Algemeen IEnumerable<T>implementeert, de verzameling wordt geserialiseerd en gedeserialiseerd volgens de IList regels:

  • Bij deserialisatie worden alle verzamelingen gedeserialiseerd door eerst een exemplaar van het type te maken door de parameterloze constructor aan te roepen, die aanwezig moet zijn voor de serializer om een verzameling als een verzameling te behandelen tijdens zowel serialisatie als deserialisatie.

  • Als dezelfde algemene verzamelingsinterface meerdere keren wordt geïmplementeerd (bijvoorbeeld als een type zowel Algemeen ICollection<T> van als Algemeen ICollection<T> van IntegerString) implementeert en er geen interface met een hogere prioriteit wordt gevonden, wordt de verzameling niet behandeld als een geldige verzameling.

  • Verzamelingstypen kunnen het SerializableAttribute kenmerk erop toepassen en kunnen de ISerializable interface implementeren. Beide worden genegeerd. Als het type echter niet volledig voldoet aan de vereisten voor het verzamelingstype (bijvoorbeeld de Add methode ontbreekt), wordt het type niet beschouwd als een verzamelingstype, en dus het SerializableAttribute kenmerk en de ISerializable interface worden gebruikt om te bepalen of het type kan worden geserialiseerd.

  • Als u het CollectionDataContractAttribute kenmerk toepast op een verzameling om het aan te passen, wordt het SerializableAttribute voorgaande terugvalmechanisme verwijderd. Als een aangepaste verzameling niet voldoet aan de vereisten voor het verzamelingstype, wordt er een InvalidDataContractException uitzondering gegenereerd. De uitzonderingsreeks bevat vaak informatie die verklaart waarom een bepaald type niet wordt beschouwd als een geldige verzameling (geen Add methode, geen parameterloze constructor, enzovoort), dus het is vaak handig om het CollectionDataContractAttribute kenmerk toe te passen voor foutopsporingsdoeleinden.

Naamgeving van verzameling

Hier volgt een lijst met naamgevingsregels voor verzamelingen:

  • De standaardnaamruimte voor alle contracten voor het verzamelen van woordenlijsten en voor lijstverzamelingsgegevenscontracten die primitieve typen bevatten, is http://schemas.microsoft.com/2003/10/Serialization/Arrays tenzij overschreven met namespace. Typen die zijn toegewezen aan ingebouwde XSD-typen, evenals chartypenTimespanGuid, worden voor dit doel beschouwd als primitieven.

  • De standaardnaamruimte voor verzamelingstypen die niet-primitieve typen bevatten, tenzij deze wordt overschreven met behulp van naamruimte, is hetzelfde als de naamruimte van het gegevenscontract van het type dat in de verzameling is opgenomen.

  • De standaardnaam voor het verzamelen van gegevenscontracten voor lijsten, tenzij overschreven met name, is de tekenreeks 'ArrayOf' in combinatie met de naam van het gegevenscontract van het type dat in de verzameling is opgenomen. De naam van het gegevenscontract voor een algemene lijst met gehele getallen is bijvoorbeeld ArrayOfint. Houd er rekening mee dat de naam van Object het gegevenscontract 'anyType' is, dus de naam van het gegevenscontract van niet-algemene lijsten zoals ArrayList 'ArrayOfanyType'.

De standaardnaam voor gegevenscontracten voor het verzamelen van woordenlijstgegevens, tenzij overschreven, Nameis de tekenreeks 'ArrayOfKeyValueOf' gecombineerd met de naam van het gegevenscontract van het sleuteltype, gevolgd door de naam van het gegevenscontract van het waardetype. De naam van het gegevenscontract voor een algemene woordenlijst van tekenreeks en geheel getal is bijvoorbeeld 'ArrayOfKeyValueOfstringint'. Als de sleutel of de waardetypen geen primitieve typen zijn, wordt bovendien een naamruimte-hash van de naamruimten van de sleutel en waardetypen toegevoegd aan de naam. Zie Namen van gegevenscontract voor meer informatie over naamruimte-hashes.

Elk gegevenscontract voor het verzamelen van woordenlijst heeft een metgezel gegevenscontract dat één vermelding in de woordenlijst vertegenwoordigt. De naam is hetzelfde als voor het woordenlijstgegevenscontract, met uitzondering van het voorvoegsel 'ArrayOf', en de naamruimte is hetzelfde als voor het woordenlijstgegevenscontract. Voor het gegevenscontract 'ArrayOfKeyValueOfstringint' vertegenwoordigt het gegevenscontract 'KeyValueofstringint' bijvoorbeeld één vermelding in de woordenlijst. U kunt de naam van dit gegevenscontract aanpassen met behulp van de ItemName eigenschap, zoals beschreven in de volgende sectie.

Algemene typenaamgevingsregels, zoals beschreven in Namen van gegevenscontracten, zijn volledig van toepassing op verzamelingstypen. Dat wil zeggen, u kunt accolades binnen Naam gebruiken om algemene typeparameters aan te geven. Getallen in de accolades verwijzen echter naar algemene parameters en niet naar typen in de verzameling.

Verzameling aanpassen

Het volgende gebruik van het CollectionDataContractAttribute kenmerk is verboden en resulteert in een InvalidDataContractException uitzondering:

Polymorfismeregels

Zoals eerder vermeld, kan het aanpassen van verzamelingen met behulp van het CollectionDataContractAttribute kenmerk de uitwisselbaarheid van verzamelingen verstoren. Twee aangepaste verzamelingstypen kunnen alleen als gelijkwaardig worden beschouwd als hun naam, naamruimte, itemnaam, evenals sleutel- en waardenamen (als dit woordenlijstverzamelingen zijn) overeenkomen.

Vanwege aanpassingen is het mogelijk om per ongeluk één gegevenscontract voor verzamelingen te gebruiken waar een ander wordt verwacht. Dit moet worden vermeden. Zie de volgende typen.

[DataContract]
public class Student
{
    [DataMember]
    public string name;
    [DataMember]
    public IList<int> testMarks;
}
public class Marks1 : List<int> {}
[CollectionDataContract(ItemName="mark")]
public class Marks2 : List<int> {}
<DataContract()>
Public Class Student

    <DataMember()>
    Public name As String

    <DataMember()>
    Public testMarks As IList(Of Integer)

End Class

Public Class Marks1
    Inherits List(Of Integer)
End Class

<CollectionDataContract(ItemName:="mark")>
Public Class Marks2
    Inherits List(Of Integer)
End Class

In dit geval kan er een instantie van Marks1 worden toegewezen aan testMarks. Marks2 Mag echter niet worden gebruikt omdat het gegevenscontract niet als gelijkwaardig aan het IList<int> gegevenscontract wordt beschouwd. De naam van het gegevenscontract is 'Marks2' en niet 'ArrayOfint', en de naam van het herhalende element is '<mark>' en niet '<int>'.

De regels in de volgende tabel zijn van toepassing op polymorfe toewijzing van verzamelingen.

Gedeclareerd type Een niet-aangepaste verzameling toewijzen Een aangepaste verzameling toewijzen
Object De contractnaam wordt geserialiseerd. De contractnaam wordt geserialiseerd.

Aanpassing wordt gebruikt.
Verzamelingsinterface De contractnaam wordt niet geserialiseerd. De contractnaam wordt niet geserialiseerd.

Aanpassing wordt niet gebruikt.*
Niet-aangepaste verzameling De contractnaam wordt niet geserialiseerd. De contractnaam wordt geserialiseerd.

Aanpassing wordt gebruikt.**
Aangepaste verzameling De contractnaam wordt geserialiseerd. Aanpassing wordt niet gebruikt.** De contractnaam wordt geserialiseerd.

Aanpassing van het toegewezen type wordt gebruikt.**

*Bij de NetDataContractSerializer klasse wordt in dit geval aanpassing gebruikt. De NetDataContractSerializer klasse serialiseert ook de werkelijke typenaam in dit geval, dus deserialisatie werkt zoals verwacht.

**Deze gevallen resulteren in ongeldige exemplaren van het schema en moeten dus worden vermeden.

In de gevallen waarin de contractnaam wordt geserialiseerd, moet het toegewezen verzamelingstype zich in de lijst met bekende typen bevinden. Het tegenovergestelde is ook waar: in de gevallen waarin de naam niet wordt geserialiseerd, is het toevoegen van het type aan de lijst met bekende typen niet vereist.

Een matrix van een afgeleid type kan worden toegewezen aan een matrix van een basistype. In dit geval wordt de contractnaam voor het afgeleide type geserialiseerd voor elk herhalend element. Als een type bijvoorbeeld is afgeleid van het type BookLibraryItem, kunt u een matrix toewijzen Book aan een matrix van LibraryItem. Dit geldt niet voor andere verzamelingstypen. U kunt bijvoorbeeld geen toewijzen Generic List of Book aan een Generic List of LibraryItem. U kunt echter wel een Generic List of LibraryItem exemplaar toewijzen dat exemplaren bevat Book . In zowel de matrix als het niet-matrixscenario Book moet zich in de lijst met bekende typen bevinden.

Verzamelingen en objectverwijzing behouden

Wanneer een serialisatiefunctie in een modus werkt waarin objectverwijzingen behouden blijven, is het behoud van objectverwijzingen ook van toepassing op verzamelingen. De objectidentiteit blijft met name behouden voor zowel volledige verzamelingen als afzonderlijke items in verzamelingen. Voor woordenlijsten blijft de objectidentiteit behouden voor zowel de objecten van het sleutel-waardepaar als de afzonderlijke sleutel- en waardeobjecten.

Zie ook