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 enNamespace
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
enNamespace
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 Type2
bevat, 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 verzamelingint
waarnaar wordt verwezen of een ander type, ongeacht of het type eenAdd
methode heeft die een methode accepteertint
of eenAdd
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=int float ,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 Integer
Integer
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 alsIXmlSerializable
.Als het gedeclareerde type is, wordt
IXmlSerializable
het geserialiseerd alsIXmlSerializable
, maar alleen als u toevoegtmyType
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 Object gebruikt. 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
Integer
String) 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, evenalschar
typenTimespan
Guid
, 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, Name
is 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:
DataContractAttribute Het kenmerk toepassen op een type waarop het CollectionDataContractAttribute kenmerk is toegepast, of op een van de afgeleide typen.
CollectionDataContractAttribute Het kenmerk toepassen op een type waarmee de IXmlSerializable interface wordt geïmplementeerd.
CollectionDataContractAttribute Het kenmerk toepassen op een niet-verzamelingstype.
Er wordt geprobeerd een kenmerk in te stellen KeyName of ValueName op te CollectionDataContractAttribute geven dat is toegepast op een niet-woordenlijsttype.
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 Book
LibraryItem
, 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.