Aracılığıyla paylaş


Veri Sözleşmelerindeki Koleksiyon Türleri

Koleksiyon, belirli bir türdeki öğelerin listesidir. .NET Framework'te, bu listeler diziler veya çeşitli diğer türler (Genel Liste, Genel BindingList<T>, StringCollectionveya ArrayList) kullanılarak temsil edilebilir. Örneğin, bir koleksiyon belirli bir Müşteri için Adreslerin listesini tutabilir. Bu koleksiyonlar, gerçek türünden bağımsız olarak liste koleksiyonları olarak adlandırılır.

Bir öğe ("anahtar") ile başka bir ("değer") arasındaki ilişkiyi temsil eden özel bir koleksiyon biçimi vardır. .NET Framework'te, Hashtable ve genel sözlük gibi türler tarafından temsil edilir. Örneğin, bir ilişkilendirme koleksiyonu bir şehri ("anahtar") nüfusuyla ("değer") eşleştirir. Bu koleksiyonlar, gerçek türleri ne olursa olsun sözlük koleksiyonları olarak adlandırılır.

Koleksiyonlar, veri sözleşmesi modelinde özel işlem alır.

Diziler ve genel koleksiyonlar dahil olmak üzere arabirimini uygulayan IEnumerable türler koleksiyon olarak kabul edilir. Bunlardan, sırasıyla IDictionary veya Genel IDictionary<TKey,TValue> arabirimlerini uygulayan türler, sözlük koleksiyonlarıdır; diğer türler liste koleksiyonlarıdır.

Adlı Add bir yönteme ve parametresiz oluşturucuya sahip olmak gibi koleksiyon türleriyle ilgili ek gereksinimler aşağıdaki bölümlerde ayrıntılı olarak ele alınmaktadır. Bu, koleksiyon türlerinin hem seri hale getirilebilmesini hem de seri durumdan çıkarılabilmesini sağlar. Bu, bazı koleksiyonların Genel ReadOnlyCollection<T> gibi doğrudan desteklenmediği anlamına gelir (parametresiz oluşturucuya sahip olmadığından). Ancak, bu kısıtlamaları aşma hakkında bilgi için bu konunun devamında yer alan "Koleksiyon Arabirim Türlerini ve Read-Only Koleksiyonları Kullanma" bölümüne bakın.

Koleksiyonlarda yer alan türler veri sözleşmesi türleri veya başka bir şekilde serileştirilebilir olmalıdır. Daha fazla bilgi için bkz. Veri Sözleşmesi Seri Hale Getiricisi Tarafından Desteklenen Türler.

Ne olduğu ve nelerin geçerli bir koleksiyon olarak kabul edilmediği ve koleksiyonların nasıl seri hale getirildiği hakkında daha fazla bilgi için, bu konunun "Gelişmiş Koleksiyon Kuralları" bölümündeki koleksiyonları serileştirme hakkındaki bilgilere bakın.

Değiştirilebilir Koleksiyonlar

Aynı türdeki tüm liste koleksiyonlarının aynı veri sözleşmesine sahip olduğu kabul edilir (bu konunun ilerleyen bölümlerinde açıklandığı gibi öznitelik kullanılarak CollectionDataContractAttribute özelleştirilmediği sürece). Bu nedenle, örneğin, aşağıdaki veri sözleşmeleri eşdeğerdir.

[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

Her iki veri sözleşmesi de aşağıdaki koda benzer xml ile sonuçlanır.

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

Koleksiyon değiştirilebilirliği, örneğin sunucuda performans için iyileştirilmiş bir koleksiyon türü ve istemcideki kullanıcı arabirimi bileşenlerine bağlanacak şekilde tasarlanmış bir koleksiyon türü kullanmanıza olanak tanır.

Liste koleksiyonlarına benzer şekilde, aynı anahtar ve değer türlerine sahip tüm sözlük koleksiyonlarının aynı veri sözleşmesine sahip olduğu kabul edilir (öznitelik tarafından CollectionDataContractAttribute özelleştirilmediği sürece).

.NET türleri için değil, koleksiyon eşdeğerliği söz konusu olduğunda yalnızca veri sözleşmesi türü önemlidir. Başka bir ifadeyle, Type1 ve Type2'nin eşdeğer veri sözleşmeleri varsa, Type1 koleksiyonu Type2 koleksiyonuna eşdeğer olarak kabul edilir.

Genel olmayan koleksiyonların türündeki Objectgenel koleksiyonlar ile aynı veri sözleşmesine sahip olduğu kabul edilir. (Örneğin, ArrayList ve List<T> için veri sözleşmeleri ile Object Generic veri sözleşmeleri aynıdır.)

Koleksiyon Arayüzü Türlerini ve Read-Only Koleksiyonlarını Kullanma

Koleksiyon arabirim türleri (IEnumerable, IDictionary, genel IDictionary<TKey,TValue>veya bu arabirimlerden türetilen arabirimler), gerçek koleksiyon türleri için koleksiyon veri sözleşmelerine eşdeğer koleksiyon veri sözleşmelerine sahip olarak da kabul edilir. Bu nedenle, koleksiyon arabirim türü olarak seri hale getirilen türü bildirmek mümkündür ve sonuçlar gerçek bir koleksiyon türü kullanılmış gibi aynıdır. Örneğin, aşağıdaki veri sözleşmeleri eşdeğerdir.

[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

Serileştirme sırasında, bildirilen tür bir arabirim olduğunda, kullanılan gerçek örnek türü bu arabirimi uygulayan herhangi bir tür olabilir. Daha önce açıklanan kısıtlamalar (parametresiz oluşturucu ve Add yönteme sahip olma) geçerli değildir. Örneğin, Generic ReadOnlyCollection<T> türünde bir veri üyesini doğrudan bildiremeseniz bile, Customer2'deki adresleri Generic ReadOnlyCollection<T> türünde bir Adres örneğine ayarlayabilirsiniz.

Seri durumdan çıkarma sırasında, bildirilen tür bir arabirim olduğunda, serileştirme motoru bildirilen arabirimi uygulayan bir tür seçer ve tür örneği oluşturulur. Bilinen türler mekanizmasının ( Veri Sözleşmesi Bilinen Türleri bölümünde açıklanmıştır) burada hiçbir etkisi yoktur; tür seçimi WCF'de yerleşiktir.

Koleksiyon Türlerini Özelleştirme

Çeşitli kullanımları olan özniteliğini CollectionDataContractAttribute kullanarak koleksiyon türlerini özelleştirebilirsiniz.

Koleksiyon türlerini özelleştirmenin koleksiyon değiştirilebilirliğini tehlikeye attığını, bu nedenle genellikle mümkün olduğunda bu özniteliğin uygulanmasını önlemenin önerildiğini unutmayın. Bu sorun hakkında daha fazla bilgi için bu konunun devamında yer alan "Gelişmiş Koleksiyon Kuralları" bölümüne bakın.

Koleksiyon Veri Sözleşmesi Adlandırma

Koleksiyon türlerini adlandırma kuralları, Veri Sözleşmesi Adları'nda açıklandığı gibi normal veri sözleşmesi türlerini adlandırmaya yönelik kurallara benzer, ancak bazı önemli farklılıklar vardır:

  • Adı özelleştirmek için CollectionDataContractAttribute özniteliği kullanılır, DataContractAttribute özniteliği yerine. Özniteliğin CollectionDataContractAttribute, Name ve Namespace özellikleri de vardır.

  • CollectionDataContractAttribute Öznitelik uygulanmadığında, koleksiyon türleri için varsayılan ad ve ad alanı koleksiyon içinde yer alan türlerin adlarına ve ad alanlarına bağlıdır. Koleksiyon türünün adından ve ad alanından etkilenmez. Bir örnek için aşağıdaki türlere bakın.

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

Her iki türün de veri sözleşmesi adı "CustomerList1" veya "StringList1" değil "ArrayOfstring" şeklindedir. Bu, bu türlerden herhangi biri kök düzeyinde seri hale getirildiğinde, aşağıdaki koda benzer XML oluşur.

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

Bu adlandırma kuralı, bir dize listesini temsil eden özelleştirilmemiş türlerin aynı veri sözleşmesine ve XML gösterimine sahip olduğundan emin olmak için seçilmiştir. Bu, koleksiyon değiştirilebilirliğini mümkün kılar. Bu örnekte CustomerList1 ve StringList1 tamamen değiştirilebilir.

Ancak, öznitelik uygulandığında CollectionDataContractAttribute , öznitelikte hiçbir özellik ayarlı olmasa bile koleksiyon özelleştirilmiş bir koleksiyon veri sözleşmesi haline gelir. Koleksiyon veri sözleşmesinin adı ve ad alanı, koleksiyon türünün kendisine bağlıdır. Bir örnek için aşağıdaki türe bakın.

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

Seri hale getirildiğinde, sonuçta elde edilen XML aşağıdakine benzer.

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

Bunun artık özelleştirilmemiş türlerin XML gösterimiyle eşdeğer olmadığına dikkat edin.

  • Name ve Namespace özelliklerini kullanarak adlandırmayı daha fazla özelleştirebilirsiniz. Aşağıdaki sınıfa bakın.

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

Sonuçta elde edilen XML aşağıdakine benzer.

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

Daha fazla bilgi için bu konunun devamında yer alan "Gelişmiş Koleksiyon Kuralları" bölümüne bakın.

Liste Koleksiyonlarında Yinelenen Öğe Adını Özelleştirme

Liste koleksiyonları yinelenen girdiler içerir. Normalde, her yinelenen girdi, koleksiyonda bulunan türün veri sözleşmesi adına uygun bir şekilde adlandırılmış bir öğe olarak temsil edilir.

Örneklerde CustomerList koleksiyonlar dizeler içeriyordu. Dize ilkel türünün veri sözleşmesi adı "string" olduğundan yinelenen öğe "<string>" idi.

Ancak özniteliğindeki ItemNameCollectionDataContractAttribute özelliği kullanılarak bu yinelenen öğe adı özelleştirilebilir. Bir örnek için aşağıdaki türe bakın.

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

Sonuçta elde edilen XML aşağıdakine benzer.

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

Yinelenen öğenin ad alanı, daha önce açıklandığı gibi özelliği kullanılarak özelleştirilebilen koleksiyon veri sözleşmesinin ad alanıyla Namespace her zaman aynıdır.

Sözlük Koleksiyonlarını Özelleştirme

Sözlük koleksiyonları temelde her girdinin bir anahtarı ve ardından bir değeri olan girdilerin listesidir. Normal listelerde olduğu gibi, özelliğini kullanarak ItemName yinelenen öğeye karşılık gelen öğe adını değiştirebilirsiniz.

Ayrıca KeyName ve ValueName özelliklerini kullanarak anahtar ve değeri temsil eden öğe adlarını değiştirebilirsiniz. Bu öğelerin ad alanları, koleksiyon veri sözleşmesinin ad alanıyla aynıdır.

Bir örnek için aşağıdaki türe bakın.

[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

Seri hale getirildiğinde, sonuçta elde edilen XML aşağıdakine benzer.

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

Sözlük koleksiyonları hakkında daha fazla bilgi için bu konunun devamında yer alan "Gelişmiş Koleksiyon Kuralları" bölümüne bakın.

Koleksiyonlar ve Bilinen Türler

Diğer koleksiyonlar veya koleksiyon arabirimleri yerine çok biçimli kullanıldığında bilinen türlere koleksiyon türleri eklemeniz gerekmez. Örneğin, türünde IEnumerable bir veri üyesi bildirir ve bunu ArrayList örneğini göndermek için kullanırsanız, ArrayList'yi bilinen türlere eklemeniz gerekmez.

Koleksiyon olmayan türler yerine çok biçimli koleksiyonlar kullandığınızda, bunların bilinen türlere eklenmesi gerekir. Örneğin, türü Object olan bir veri üyesi bildirir ve bunu ArrayList örneğini göndermek için kullanırsanız, ArrayList'yi bilinen türlere ekleyin.

Bu, eşdeğer koleksiyonları çok biçimli olarak seri hale getirmenize izin vermez. Örneğin, önceki örnekte ArrayList'yi bilinen türler listesine eklediğinizde, sınıfın Array of Object eşdeğer bir veri sözleşmesi olmasına rağmen onu atamanıza izin vermez. Bu, koleksiyon olmayan türler için serileştirmede bilinen normal tür davranışından farklı değildir, ancak koleksiyonların eşdeğer olması çok yaygın olduğundan koleksiyonlar söz konusu olduğunda anlaşılması özellikle önemlidir.

Serileştirme sırasında, belirli bir veri sözleşmesi için belirli bir kapsamda yalnızca bir tür bilinebilir ve eşdeğer koleksiyonların tümü aynı veri sözleşmelerine sahiptir. Bu, önceki örnekte hem ArrayList hem de Array of Object bilinen türleri aynı kapsamda ekleyemeyeceğiniz anlamına gelir. Bu, koleksiyon dışı türler için bilinen tür davranışına eşdeğerdir, ancak koleksiyonları anlamak özellikle önemlidir.

Koleksiyonların içeriği için bilinen türler de gerekebilir. Örneğin, bir ArrayList, Type1 ve Type2 örneklerini gerçekten içeriyorsa, bu türlerin her ikisi de bilinen türlere eklenmelidir.

Aşağıdaki örnekte koleksiyonlar ve bilinen türler kullanılarak düzgün bir şekilde leştirilmiş bir nesne grafı gösterilmektedir. Örnek biraz karmaşıktır, çünkü gerçek bir uygulamada normalde aşağıdaki veri üyelerini olarak Objecttanımlamazsınız ve bu nedenle bilinen bir tür/polimorfizm sorunu yoktur.

[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

Serileştirme işlemi sırasında, bildirilen tür bir koleksiyon türüyse, gerçekten iletilen türden bağımsız olarak bu bildirilen türün örneği oluşturulur. Bildirilen tür bir koleksiyon arabirimiyse, seri durumdan çıkarıcı bilinen türleri dikkate almadan örneklenmek üzere bir tür seçer.

Ayrıca seri durumdan çıkarmada, bildirilen tür bir koleksiyon türü değilse ancak bir koleksiyon türü gönderiliyorsa, bilinen türler listesinden eşleşen bir koleksiyon türü seçilir. Seri durumdan çıkarma sırasında bilinen türler listesine koleksiyon arabirimi türleri eklemek mümkündür. Bu durumda, seri durumdan çıkarma motoru yeniden örneklenecek bir tür seçer.

Koleksiyonlar ve NetDataContractSerializer Sınıfı

NetDataContractSerializer Sınıf kullanımda olduğunda, dizi olmayan özelleştirilmemiş koleksiyon türleri (özniteliği olmadanCollectionDataContractAttribute) özel anlamlarını kaybeder.

Özelleştirilmemiş koleksiyon türleri, SerializableAttribute özniteliğiyle işaretlendiklerinde yine de NetDataContractSerializer özniteliği veya SerializableAttribute arabirim kurallarına göre ISerializable sınıfı tarafından serileştirilebilir.

Özelleştirilmiş koleksiyon türleri, koleksiyon arabirimleri ve diziler, sınıf kullanımda olsa bile koleksiyon olarak değerlendirilmeye NetDataContractSerializer devam eder.

Koleksiyonlar ve Şema

Tüm eşdeğer koleksiyonlar XML Şema tanım dili (XSD) şemasında aynı temsile sahiptir. Bu nedenle, normalde oluşturulan istemci kodunda sunucudakiyle aynı koleksiyon türünü almazsınız. Örneğin, sunucu, Tamsayı veri üyesi içeren bir Genel List<T> veri sözleşmesi kullanabilir, ancak oluşturulan istemci kodunda aynı veri üyesi bir tamsayı dizisi haline gelebilir.

Sözlük koleksiyonları, sözlük olduklarını belirten WCF'ye özgü bir şema ek açıklamasıyla işaretlenir; aksi takdirde, anahtar ve değer içeren girdiler içeren basit listelerden ayırt edilemez. Koleksiyonların veri sözleşmesi şemasında nasıl temsil edildiklerine ilişkin tam bir açıklama için bkz. Veri Sözleşmesi Şema Başvurusu.

Varsayılan olarak, içeri aktarılan koddaki özelleştirilmemiş koleksiyonlar için türler oluşturulmaz. Liste koleksiyonu türlerinin veri üyeleri diziler olarak, sözlük koleksiyonu türlerinin veri üyeleri de Genel Sözlük olarak içeri aktarılır.

Ancak, özelleştirilmiş koleksiyonlar için özniteliğiyle CollectionDataContractAttribute işaretlenmiş ayrı türler oluşturulur. (Şemadaki özelleştirilmiş koleksiyon türü, varsayılan ad alanını, adı, yinelenen öğe adını veya anahtar/değer öğesi adlarını kullanmayan bir koleksiyon türüdür.) Bu türler, liste türleri için Genel List<T> ve sözlük türleri için Genel Sözlük'ten türetilen boş türlerdir.

Örneğin, sunucuda aşağıdaki türlere sahip olabilirsiniz.

[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

Şema dışarı aktarılıp yeniden içeri aktarıldığında, oluşturulan istemci kodu aşağıdakine benzer (okuma kolaylığı için özellikler yerine alanlar gösterilir).

[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

Oluşturulan kodda varsayılan kodlardan farklı türler kullanmak isteyebilirsiniz. Örneğin, veri üyelerinizi kullanıcı arabirimi bileşenlerine bağlamayı kolaylaştırmak için normal diziler yerine Genel BindingList<T> kullanmak isteyebilirsiniz.

Oluşturulacak koleksiyon türlerini seçmek için, şemayı içeri aktarırken kullanmak istediğiniz koleksiyon türlerinin listesini nesnenin özelliğine ReferencedCollectionTypesImportOptions geçirin. Bu türlere atıfta bulunulan koleksiyon türleri denir.

Genel türlere başvurulduğunda, bunların tamamen açık genel türler veya tamamen kapalı genel türler olması gerekir.

Uyarı

Svcutil.exe aracı kullanılırken, bu başvuru /collectionType komut satırı anahtarı (kısa form: /ct) kullanılarak gerçekleştirilebilir. /reference anahtarını (kısa form: /r) kullanarak başvuruda bulunılan koleksiyon türleri için derlemeyi de belirtmeniz gerektiğini unutmayın. Tür genelse, arkasına bir geri tırnak işareti ve genel parametre sayısı gelmelidir. Geri tırnak işareti (') tek tırnak (') karakteriyle karıştırılmamalıdır. /collectionType anahtarını birden çok kez kullanarak birden çok başvuruda bulunan koleksiyon türü belirtebilirsiniz.

Örneğin, tüm listelerin Genel List<T>olarak içeri aktarılmasına neden olmak için.

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

Herhangi bir koleksiyonu içeri aktarırken, başvurulan koleksiyon türlerinin listesi taranır ve en iyi eşleşen koleksiyon, veri üyesi türü (özelleştirilmemiş koleksiyonlar için) veya türetilmesi gereken temel tür (özelleştirilmiş koleksiyonlar için) olarak bulunursa kullanılır. Sözlükler yalnızca sözlüklerle eşleştirilirken, listeler listelerle eşleştirilir.

Örneğin, Genel'i BindingList<T> ve Hashtable başvuruda bulunan türler listesine eklerseniz, önceki örnek için oluşturulan istemci kodu aşağıdakine benzer.

[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

Başvurulan koleksiyon türlerinizin bir parçası olarak koleksiyon arabirimi türlerini belirtebilirsiniz, ancak geçersiz koleksiyon türleri belirtemezsiniz (yöntem veya ortak oluşturucu olmayan Add türler gibi).

Kapalı genel, en iyi eşleşme olarak kabul edilir. (Genel olmayan türler, 'nin kapalı genel türlerine Objecteşdeğer olarak kabul edilir). Örneğin, Genel List<T>DateTimeBindingList<T> (açık genel) türleri ve ArrayList başvuruda bulunan koleksiyon türleriyse, aşağıdakiler oluşturulur.

[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

Liste koleksiyonları için yalnızca aşağıdaki tabloda yer alan durumlar desteklenir.

Başvurulan tür Başvurulan tür tarafından uygulanan arabirim Örnek Tür olarak ele alındı:
Genel olmayan veya kapalı genel (herhangi bir sayıda parametre) Genel olmayan MyType : IList

veya

MyType<T> : IList

where T= int
kapalı jenerik Object (örneğin, IList<object>)
Genel olmayan veya kapalı genel (koleksiyon türüyle eşleşmesi gerekmeyen herhangi bir sayıda parametre) Kapalı jenerik MyType : IList<string>

veya

MyType<T> : IList<string> where T=int
Kapalı genel (örneğin, IList<string>)
Herhangi bir sayıda parametreyle kapalı genellik Türün parametrelerinden herhangi birini kullanarak genel'i açın MyType<T,U,V> : IList<U>

where T=int, U=string, V=bool
Kapalı genel (örneğin, IList<string>)
Tek bir parametreyle genel'i açma Türün parametresini kullanarak genel'i açın MyType<T> : IList<T>, T açık Açık genel (örneğin, IList<T>)

Bir tür birden fazla liste koleksiyonu arabirimi uygularsa, aşağıdaki kısıtlamalar geçerlidir:

  • Tür, Genel IEnumerable<T> (veya türetilmiş arayüzlerini) farklı türler için birden çok kez uygularsa, tür geçerli bir referans koleksiyon türü olarak kabul edilmez ve yoksayılır. Bazı uygulamalar geçersiz olsa veya açık genel değerler kullansa bile bu durum geçerlidir. Örneğin, IEnumerable<T> ve T'nin int Genel'ini ve IEnumerable<T> Uygulayan bir tür, türün int veya başka bir tür üzerinde başvurulan koleksiyon olarak hiçbir zaman kullanılmaz. Bu, Add yöntemi int kabul etmiş veya Add yönteminde T türünde bir parametre kabul etmiş veya her ikisine sahip olsa bile böyledir.

  • Tür, IList ile birlikte genel bir koleksiyon arabirimini de uyguluyorsa, genel koleksiyon arabirimi Object türünde kapalı bir genellik olmadığı sürece tür asla başvurulan bir koleksiyon türü olarak kullanılmaz.

Sözlük koleksiyonları için yalnızca aşağıdaki tabloda yer alan durumlar desteklenir.

Başvurulan tür Başvurulan tür tarafından uygulanan arabirim Örnek Tür olarak ele alındı
Genel olmayan veya kapalı genel (herhangi bir sayıda parametre) IDictionary MyType : IDictionary

veya

MyType<T> : IDictionary where T=int
Kapalı genel IDictionary<object,object>
Kapalı genel (herhangi bir sayıda parametre) IDictionary<TKey,TValue> kapalı MyType<T> : IDictionary<string, bool> where T=int Kapalı genel (örneğin, IDictionary<string,bool>)
Kapalı genel (herhangi bir sayıda parametre) Genel IDictionary<TKey,TValue>, anahtar veya değerlerden biri kapalı, diğeri açık ve türün parametrelerinden birini kullanıyor MyType<T,U,V> : IDictionary<string,V> where T=int, U=float,V=bool

veya

MyType<Z> : IDictionary<Z,bool> where Z=string
Kapalı genel (Örneğin, IDictionary<string,bool>)
Kapalı genel (herhangi bir sayıda parametre) Genel IDictionary<TKey,TValue>, hem anahtar hem de değer açıktır ve her biri türün parametrelerinden birini kullanır MyType<T,U,V> : IDictionary<V,U> where T=int, U=bool, V=string Kapalı genel (örneğin, IDictionary<string,bool>)
Açık jenerik (iki parametre) Genel IDictionary<TKey,TValue>, open, türün genel parametrelerinin her ikisini de göründükleri sırayla kullanır MyType<K,V> : IDictionary<K,V>, K ve V her ikisi de açık Açık genel (örneğin, IDictionary<K,V>)

Tür, hem IDictionary hem de Genel IDictionary<TKey,TValue> uygularsa, yalnızca Genel IDictionary<TKey,TValue> dikkate alınır.

Kısmi genel türlere başvuruda bulunmak desteklenmez.

Çoğaltmalara izin verilmez, örneğin, hem Genel List<T> hem Integer de Genel Koleksiyonu'nu IntegerReferencedCollectionTypesöğesine ekleyemezsiniz, çünkü bu, şemada bir tamsayı listesi bulunduğunda hangisinin kullanılacağını belirlemeyi imkansız hale getirir. Yinelemeler yalnızca şemada yinelenenler sorununu ortaya çıkaran bir tür varsa algılanır. Örneğin, içeri aktarılan şema tamsayı listeleri içermiyorsa, hem List<T>'ın Integer'i hem de Integer'nin Genel Koleksiyonu ReferencedCollectionTypes içinde bulunabilir, ancak bunlardan hiçbirinin etkisi yoktur.

Gelişmiş Koleksiyon Kuralları

Koleksiyonları Seri Hale Getirme

Serileştirme için koleksiyon kurallarının listesi aşağıdadır:

  • Koleksiyon türlerini birleştirmeye (koleksiyonlardan oluşan koleksiyonlar) izin verilir. Düzensiz diziler, koleksiyonların koleksiyonu olarak değerlendirilir. Çok boyutlu diziler desteklenmez.

  • Bayt dizileri ve dizileri XmlNode , koleksiyonlar değil, ilkel olarak ele alınan özel dizi türleridir. Bayt dizisini seri hale getirme işlemi, her bayt için ayrı bir öğe yerine Base64 ile kodlanmış veri öbeği içeren tek bir XML öğesiyle sonuçlanır. Bir dizi XmlNode'nin nasıl ele alındığı hakkında daha fazla bilgi için bkz. Veri Sözleşmelerinde XML ve ADO.NET Türleri. Elbette, bu özel türler koleksiyonlara katılabilir: bayt dizisi dizisi, her biri Base64 ile kodlanmış veri öbeği içeren birden çok XML öğesiyle sonuçlanır.

  • DataContractAttribute Öznitelik bir koleksiyon türüne uygulanırsa, tür koleksiyon olarak değil normal bir veri sözleşmesi türü olarak değerlendirilir.

  • Bir koleksiyon türü arabirimini uygularsa IXmlSerializable , türüne göre myType:IList<string>, IXmlSerializableaşağıdaki kurallar uygulanır:

    • Bildirilen tür ise IList<string>, tür liste olarak serileştirilir.

    • Bildirilen tür myType ise, IXmlSerializable olarak serileştirilir.

    • Bildirilen tür IXmlSerializable ise, IXmlSerializable olarak serileştirilir, ancak yalnızca myType bilinen türler listesine eklerseniz.

  • Koleksiyonlar, aşağıdaki tabloda gösterilen yöntemler kullanılarak seri hale getirilir ve seri durumdan çıkarılır.

Koleksiyon türü uygulamalara sahiptir Serileştirme sırasında çağrılan yöntem(ler) Seri durumdan çıkarmada (deserialization) çağrılan yöntemler
Genel IDictionary<TKey,TValue> get_Keys, get_Values Genel Ekle
IDictionary get_Keys, get_Values Add
Genel IList<T> Genel IList<T> dizin oluşturucu Genel Ekle
Genel ICollection<T> Numaralayıcı Genel Ekle
IList IList Dizinleyici Add
Genel IEnumerable<T> GetEnumerator Adlı Add statik olmayan bir yöntem, uygun türde bir parametre alır (genel parametrenin türü veya temel türlerinden biri). Bir koleksiyon türünü seri hale getirme ve seri durumdan çıkarma sırasında koleksiyon olarak ele almak için böyle bir yöntem mevcut olmalıdır.
IEnumerable (ve bu nedenle ICollection, ondan türetilir) GetEnumerator Statik olmayan ve Add türünde bir parametre alan Object adlı bir yöntem. Bir koleksiyon türünü seri hale getirme ve seri durumdan çıkarma sırasında koleksiyon olarak ele almak için böyle bir yöntem mevcut olmalıdır.

Yukarıdaki tabloda koleksiyon arabirimleri azalan öncelik sırasına göre listeleniyor. Örneğin, bir tür hem IList hem de Genel IEnumerable<T> uygularsa, koleksiyon IList kurallarına göre serileştirilir ve seri durumdan çıkarılır.

  • Seri durumdan çıkarma işlemi sırasında, tüm koleksiyonlar önce parametresiz oluşturucu çağrılarak türün bir örneği oluşturularak seri durumdan çıkarılır. Bu parametresiz oluşturucu, serileştirme ve seri durumdan çıkarma sırasında seri hale getiricinin bir koleksiyon türünü koleksiyon olarak ele alabilmesi için mevcut olmalıdır.

  • Aynı genel koleksiyon arabirimi birden çok kez uygulanıyorsa (örneğin, bir tür hem Genel ICollection<T>Integer hem de Genel ICollection<T>Stringolarak uygulanıyorsa) ve daha yüksek öncelikli arabirim bulunamazsa, koleksiyon geçerli bir koleksiyon olarak kabul edilmez.

  • Koleksiyon tipleri SerializableAttribute özelliğini taşıyabilir ve ISerializable arabirimini uygulayabilir. Bunların ikisi de yoksayılır. Ancak, tür koleksiyon türü gereksinimlerini tam olarak karşılamıyorsa (örneğin, Add yöntem eksikse), tür koleksiyon türü olarak kabul edilmez ve bu nedenle türün SerializableAttributeISerializable serileştirilip serileştirilemeyeceğini belirlemek için öznitelik ve arabirim kullanılır.

  • Bir koleksiyonu özelleştirmek için CollectionDataContractAttribute özniteliğini uygulamak, önceden SerializableAttribute geri dönüş mekanizmasını kaldırır. Bunun yerine, özelleştirilmiş bir koleksiyon koleksiyon türü gereksinimlerini karşılamıyorsa, bir InvalidDataContractException özel durum oluşturulur. Özel durum dizesi genellikle belirli bir türün neden geçerli bir koleksiyon olarak kabul edilmediğini açıklayan bilgiler içerir (yöntem yok Add , parametresiz oluşturucu yok vb.), bu nedenle hata ayıklama amacıyla özniteliğini CollectionDataContractAttribute uygulamak genellikle yararlıdır.

Koleksiyon Adlandırma

Koleksiyon adlandırma kurallarının listesi aşağıdadır:

  • Tüm sözlük koleksiyonu veri sözleşmeleri ve ilkel türler içeren liste koleksiyonu veri sözleşmeleri için varsayılan ad alanı, Namespace kullanılarak geçersiz kılınmadığı sürece http://schemas.microsoft.com/2003/10/Serialization/Arrays’dir. Yerleşik XSD türlerinin yanı sıra char, Timespanve Guid türleriyle eşlenen türler, bu amaçla ilkel olarak kabul edilir.

  • Ad Alanı kullanılarak geçersiz kılınmadığı sürece, ilkel olmayan türler içeren koleksiyon türleri için varsayılan ad alanı, koleksiyonda yer alan türün veri sözleşmesi ad alanıyla aynıdır.

  • Ad kullanılarak geçersiz kılınmadığı sürece, liste koleksiyonu veri sözleşmelerinin varsayılan adı, koleksiyonda yer alan türün veri sözleşmesi adıyla birleştirilen "ArrayOf" dizesidir. Örneğin, Genel Tamsayı listesi için veri sözleşmesi adı "ArrayOfint" şeklindedir. Veri sözleşmesi adının Object "anyType" olduğunu, dolayısıyla genel olmayan listelerin ArrayList veri sözleşmesi adının "ArrayOfanyType" olduğunu unutmayın.

kullanılarak Namegeçersiz kılınmadığı sürece sözlük koleksiyonu veri sözleşmeleri için varsayılan ad, anahtar türünün veri sözleşmesi adı ve ardından değer türünün veri sözleşmesi adıyla birleştirilen "ArrayOfKeyValueOf" dizesidir. Örneğin, Dize ve Tamsayı genel sözlüğü için veri sözleşmesi adı "ArrayOfKeyValueOfstringint" şeklindedir. Ayrıca, anahtar veya değer türleri temel türler değilse, veri sözleşmesinin anahtar ve değer türlerine ait ad alanlarından elde edilen ad alanı karması, adın sonuna eklenir. Ad alanı karmaları hakkında daha fazla bilgi için bkz. Veri Sözleşmesi Adları.

Her sözlük toplama veri sözleşmesi, sözlükteki bir girişi temsil eden bir yardımcı veri sözleşmesine sahiptir. "ArrayOf" ön eki dışında adı sözlük veri sözleşmesiyle aynıdır ve ad alanı sözlük veri sözleşmesiyle aynıdır. Örneğin, "ArrayOfKeyValueOfstringint" sözlük veri sözleşmesi için "KeyValueofstringint" veri sözleşmesi sözlükteki bir girişi temsil eder. Bu veri sözleşmesinin adını, sonraki bölümde açıklandığı gibi özelliğini kullanarak ItemName özelleştirebilirsiniz.

Veri Sözleşmesi Adlarında açıklandığı gibi genel tür adlandırma kuralları koleksiyon türlerine tam olarak uygulanır; yani, genel tür parametrelerini belirtmek için Ad içindeki küme ayraçlarını kullanabilirsiniz. Ancak, küme ayraçları içindeki sayılar, koleksiyondaki türler yerine genel parametrelere başvurur.

Koleksiyon Özelleştirme

özniteliğinin CollectionDataContractAttribute aşağıdaki kullanımları yasaklanmıştır ve bir InvalidDataContractException özel durumla sonuçlanır:

Çok biçimlilik Kuralları

Daha önce de belirtildiği gibi, özniteliğini kullanarak koleksiyonları CollectionDataContractAttribute özelleştirmek koleksiyonların değiştirilebilirliğini etkileyebilir. İki özelleştirilmiş koleksiyon türü yalnızca adları, ad alanları, öğe adları, anahtar ve değer adları (sözlük koleksiyonlarıysa) eşleşiyorsa eşdeğer olarak kabul edilebilir.

Özelleştirmeler nedeniyle, bir toplama veri sözleşmesini yanlışlıkla başka bir toplama veri sözleşmesinin beklendiği yerde kullanmak mümkündür. Bundan kaçınılmalıdır. Aşağıdaki türlere bakın.

[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

Bu durumda, bir Marks1 örneği testMarks'ye atanabilir. Ancak, Marks2 veri sözleşmesi veri sözleşmesiyle IList<int> eşdeğer olarak kabul edilmediğinden kullanılmamalıdır. Veri sözleşmesi adı "ArrayOfint" değil "Marks2" ve yinelenen öğe adı "int<" değil "><mark>" olur.

Aşağıdaki tabloda yer alan kurallar, koleksiyonların çok biçimli ataması için geçerlidir.

Bildirilen tür Özelleştirilmemiş koleksiyon atama Özelleştirilmiş bir koleksiyonun atanması
Nesne Sözleşme adı seri hale getirilir. Sözleşme adı seri hale getirilir.

Özelleştirme kullanılır.
Koleksiyon arabirimi Sözleşme adı serileştirilmemiş. Sözleşme adı serileştirilmemiş.

Özelleştirme kullanılmaz.*
Özelleştirilmemiş koleksiyon Sözleşme adı serileştirilmemiş. Sözleşme adı seri hale getirilir.

Özelleştirme kullanılır.**
Özelleştirilmiş koleksiyon Sözleşme adı seri hale getirilir. Özelleştirme kullanılmaz.** Sözleşme adı seri hale getirilir.

Atanan türün özelleştirmesi kullanılır.**

NetDataContractSerializer sınıfı kullanılarak bu durumda özelleştirme yapılır. sınıfı NetDataContractSerializer da bu durumda gerçek tür adını serileştirir, bu nedenle seri durumdan çıkarma beklendiği gibi çalışır.

**Bu durumlar şema geçersiz örneklerle sonuçlanır ve bu nedenle kaçınılmalıdır.

Sözleşme adının seri hale getirildiği durumlarda, atanan koleksiyon türü bilinen türler listesinde olmalıdır. Tam tersi de geçerlidir: Adın serileştirilmediği durumlarda, türü bilinen türler listesine eklemek gerekli değildir.

Türetilmiş türden bir dizinin, temel türden bir diziye atanması mümkündür. Bu durumda, türetilen türün sözleşme adı, yinelenen her öğe için serileştirilir. Örneğin, bir Book türü LibraryItem türünden türetilirse, Book dizisini LibraryItem dizisine atayabilirsiniz. Bu, diğer koleksiyon türleri için geçerli değildir. Örneğin, bir Generic List of Book öğesine Generic List of LibraryItematayamazsınız. Ancak Generic List of LibraryItem örnekleri içeren bir Book atayabilirsiniz. Hem dizide hem de dizi dışı durumda, Book bilinen türler listesinde olmalıdır.

Koleksiyonlar Koruması ve Nesne Referansı Korunması

Seri hale getirici, nesne başvurularını koruduğu bir modda çalıştığında, nesne başvurusu koruması koleksiyonlar için de geçerlidir. Özellikle, nesne kimliği hem koleksiyonların tamamı hem de koleksiyonlarda yer alan tek tek öğeler için korunur. Sözlükler için nesne kimliği hem anahtar/değer çifti nesneleri hem de tek tek anahtar ve değer nesneleri için korunur.

Ayrıca bakınız